def _perpetual_path_request(self, paths, length_params, perpetual_range_start=None,
                                no_limit_req=False):
        """Perform a perpetual path request against the Shakti API to retrieve
        a possibly large video list. If the requested video list's size is
        larger than MAX_PATH_REQUEST_SIZE, multiple path requests will be
        executed with forward shifting range selectors and the results will
        be combined into one path response."""
        response_type, length_args = length_params
        context_name = length_args[0]
        response_length = apipaths.LENGTH_ATTRIBUTES[response_type]

        request_size = apipaths.MAX_PATH_REQUEST_SIZE
        response_size = request_size + 1
        # Note: when the request is made with 'genres' or 'seasons' context,
        # the response strangely does not respect the number of objects
        # requested, returning 1 more item, i couldn't understand why
        if context_name in ['genres', 'seasons']:
            response_size += 1

        number_of_requests = 100 if no_limit_req else 2
        perpetual_range_start = int(perpetual_range_start) if perpetual_range_start else 0
        range_start = perpetual_range_start
        range_end = range_start + request_size
        merged_response = {}

        for n_req in range(number_of_requests):
            path_response = self._path_request(
                _set_range_selector(paths, range_start, range_end))
            if not path_response:
                break
            if not common.check_path_exists(length_args, path_response):
                # It may happen that the number of items to be received
                # is equal to the number of the response_size
                # so a second round will be performed, which will return an empty list
                break
            common.merge_dicts(path_response, merged_response)
            response_count = response_length(path_response, *length_args)
            if response_count < response_size:
                # There are no other elements to request
                break

            range_start += response_size
            if n_req == (number_of_requests - 1):
                merged_response['_perpetual_range_selector'] = {'next_start': range_start}
                common.debug('{} has other elements, added _perpetual_range_selector item',
                             response_type)
            else:
                range_end = range_start + request_size

        if perpetual_range_start > 0:
            previous_start = perpetual_range_start - (response_size * number_of_requests)
            if '_perpetual_range_selector' in merged_response:
                merged_response['_perpetual_range_selector']['previous_start'] = previous_start
            else:
                merged_response['_perpetual_range_selector'] = {
                    'previous_start': previous_start}
        return merged_response
    def req_video_list_chunked(self, chunked_video_list, perpetual_range_selector=None):
        """Retrieve a video list which contains the video ids specified"""
        if not any(isinstance(item, list) for item in chunked_video_list):
            raise InvalidVideoListTypeError('The chunked_video_list not contains a list of a list of videoids')
        merged_response = {}
        for videoids_list in chunked_video_list:
            path = build_paths(['videos', videoids_list], VIDEO_LIST_PARTIAL_PATHS)
            path_response = self.nfsession.path_request(path)
            common.merge_dicts(path_response, merged_response)

        if perpetual_range_selector:
            merged_response.update(perpetual_range_selector)
        return CustomVideoList(merged_response)
Exemplo n.º 3
0
    def perpetual_path_request(self,
                               paths,
                               path_type,
                               length_params1=None,
                               length_params2=None):
        """Perform a perpetual path request against the Shakti API to retrieve
        a possibly large video list. If the requested video list's size is
        larger than MAX_PATH_REQUEST_SIZE, multiple path requests will be
        executed with forward shifting range selectors and the results will
        be combined into one path response."""
        if length_params2 is None:
            length_params = [length_params1]
        else:
            length_params = [length_params1, length_params2]
        length = apipaths.LENGTH_ATTRIBUTES[path_type]
        range_start = 0
        range_end = MAX_PATH_REQUEST_SIZE
        range_limit = int(g.ADDON.getSetting('list_limit_results'))\
            if common.is_numeric(g.ADDON.getSetting('list_limit_results')) else 0
        merged_response = {}
        while range_start < range_end:
            # We limit the number of results of the list, a very high number has more chance of causing,
            # AddonSignals call timed out, for the time it takes to request information
            # Would be more suitable that when you reach the end of the list,
            # you load the next block of results.
            if range_start >= range_limit > 0:
                range_start = range_end
                continue

            path_response = self._path_request(
                _set_range_selector(paths, range_start, range_end))

            common.debug('perpetual_path_request path_response: ' +
                         str(path_response))
            range_start = range_end + 1
            if len(path_response) != 0:
                common.merge_dicts(path_response, merged_response)

                videos_count = length(path_response, *
                                      length_params) - 1  #has zero base

                # If the number of video elements is lower, we've come to the end
                # Note: when the request is made with 'genre' context,
                #  the response strangely does not respect the number of objects requested,
                #  returning 2 more items, i couldn't understand why
                if videos_count >= MAX_PATH_REQUEST_SIZE:
                    common.debug(
                        '{} has more items, doing another path request'.format(
                            path_type))
                    range_end += MAX_PATH_REQUEST_SIZE + 1
        return merged_response
Exemplo n.º 4
0
    def perpetual_path_request(self, paths, length_params, perpetual_range_start=None):
        """Perform a perpetual path request against the Shakti API to retrieve
        a possibly large video list. If the requested video list's size is
        larger than MAX_PATH_REQUEST_SIZE, multiple path requests will be
        executed with forward shifting range selectors and the results will
        be combined into one path response."""
        response_type, length_args = length_params
        context_name = length_args[0]
        response_length = apipaths.LENGTH_ATTRIBUTES[response_type]

        request_size = apipaths.MAX_PATH_REQUEST_SIZE
        response_size = request_size + 1
        # Note: when the request is made with 'genres' context,
        # the response strangely does not respect the number of objects
        # requested, returning 1 more item, i couldn't understand why
        if context_name == 'genres':
            response_size += 1

        number_of_requests = 2
        perpetual_range_start = int(perpetual_range_start) if perpetual_range_start else 0
        range_start = perpetual_range_start
        range_end = range_start + request_size
        merged_response = {}

        for n_req in range(number_of_requests):
            path_response = self._path_request(_set_range_selector(paths, range_start, range_end))
            if len(path_response) != 0:
                common.merge_dicts(path_response, merged_response)
                response_count = response_length(path_response, *length_args)
                if response_count >= response_size:
                    range_start += response_size
                    if n_req == (number_of_requests - 1):
                        merged_response['_perpetual_range_selector'] = {'next_start': range_start}
                        common.debug('{} has other elements, added _perpetual_range_selector item'.format(response_type))
                    else:
                        range_end = range_start + request_size
                else:
                    # There are no other elements to request
                    break
            else:
                break

        if perpetual_range_start > 0:
            previous_start = perpetual_range_start - (response_size * number_of_requests)
            if '_perpetual_range_selector' in merged_response:
                merged_response['_perpetual_range_selector']['previous_start'] = previous_start
            else:
                merged_response['_perpetual_range_selector'] = {'previous_start': previous_start}
        return merged_response
def chunked_custom_video_list(chunked_video_list):
    """Retrieve a video list which contains the videos specified by video_ids"""
    chunked_video_ids = chunked_video_list['video_ids']
    common.debug('Requesting custom video list with {} chunked video list',
                 len(chunked_video_ids))
    merged_response = {}
    for video_ids in chunked_video_ids:
        path_response = common.make_call(
            'path_request',
            build_paths(['videos', video_ids], VIDEO_LIST_PARTIAL_PATHS))
        common.merge_dicts(path_response, merged_response)

    perpetual_range_selector = chunked_video_list['perpetual_range_selector']
    if perpetual_range_selector:
        merged_response.update(perpetual_range_selector)
    return CustomVideoList(merged_response)
Exemplo n.º 6
0
 def perpetual_path_request(self, paths, path_type, length_params=None):
     """Perform a perpetual path request against the Shakti API to retrieve
     a possibly large video list. If the requested video list's size is
     larger than MAX_PATH_REQUEST_SIZE, multiple path requests will be
     executed with forward shifting range selectors and the results will
     be combined into one path response."""
     length_params = length_params or []
     length = apipaths.LENGTH_ATTRIBUTES[path_type]
     range_start = 0
     range_end = MAX_PATH_REQUEST_SIZE
     merged_response = {}
     while range_start < range_end:
         path_response = self._path_request(
             _set_range_selector(paths, range_start, range_end))
         common.merge_dicts(path_response, merged_response)
         range_start = range_end + 1
         if length(path_response, *length_params) > range_end:
             common.debug(
                 '{} has more items, doing another path request'.format(
                     path_type))
             range_end += MAX_PATH_REQUEST_SIZE
     return merged_response
    def perpetual_path_request(
            self,
            paths,
            length_params,
            perpetual_range_start=None,
            request_size=apipaths.PATH_REQUEST_SIZE_PAGINATED,
            no_limit_req=False):
        """
        Perform a perpetual path request against the Shakti API to retrieve a possibly large video list.
        :param paths: The paths that compose the request
        :param length_params: A list of two values, e.g. ['stdlist', [...]]:
                              1: A key of LENGTH_ATTRIBUTES that define where read the total number of objects
                              2: A list of keys used to get the list of objects in the JSON data of received response
        :param perpetual_range_start: defines the starting point of the range of objects to be requested
        :param request_size: defines the size of the range, the total number of objects that will be received
        :param no_limit_req: if True, the perpetual cycle of requests will be 'unlimited'
        :return: Union of all JSON raw data received
        """
        # When the requested video list's size is larger than 'request_size',
        # multiple path requests will be executed with forward shifting range selectors
        # and the results will be combined into one path response.
        response_type, length_args = length_params
        context_name = length_args[0]
        response_length = apipaths.LENGTH_ATTRIBUTES[response_type]

        # Note: when the request is made with 'genres' or 'seasons' context,
        #   the response strangely does not respect the number of objects
        #   requested, returning 1 more item, i couldn't understand why
        if context_name in ['genres', 'seasons']:
            request_size -= 1
        response_size = request_size + 1
        if context_name in ['genres', 'seasons']:
            response_size += 1

        number_of_requests = 100 if no_limit_req else int(
            G.ADDON.getSettingInt('page_results') / 45)
        perpetual_range_start = int(
            perpetual_range_start) if perpetual_range_start else 0
        range_start = perpetual_range_start
        range_end = range_start + request_size
        merged_response = {}

        for n_req in range(number_of_requests):
            path_response = self.path_request(
                _set_range_selector(paths, range_start, range_end))
            if not path_response:
                break
            if not common.check_path_exists(length_args, path_response):
                # It may happen that the number of items to be received
                # is equal to the number of the response_size
                # so a second round will be performed, which will return an empty list
                break
            common.merge_dicts(path_response, merged_response)
            response_count = response_length(path_response, *length_args)
            if response_count < response_size:
                # There are no other elements to request
                break

            range_start += response_size
            if n_req == (number_of_requests - 1):
                merged_response['_perpetual_range_selector'] = {
                    'next_start': range_start
                }
                common.debug(
                    '{} has other elements, added _perpetual_range_selector item',
                    response_type)
            else:
                range_end = range_start + request_size

        if perpetual_range_start > 0:
            previous_start = perpetual_range_start - (response_size *
                                                      number_of_requests)
            if '_perpetual_range_selector' in merged_response:
                merged_response['_perpetual_range_selector'][
                    'previous_start'] = previous_start
            else:
                merged_response['_perpetual_range_selector'] = {
                    'previous_start': previous_start
                }
        return merged_response