def req_lolomo_list_genre(self, genre_id): """Retrieve LoLoMos for the given genre""" common.debug('Requesting LoLoMo for genre {}', genre_id) paths = ( build_paths(['genres', genre_id, 'rw'], GENRE_PARTIAL_PATHS) + # Titles and art of standard lists' items build_paths([ 'genres', genre_id, 'rw', { "from": 0, "to": 48 }, { "from": 0, "to": 3 }, "reference" ], [['title', 'summary']] + ART_PARTIAL_PATHS) + # IDs and names of sub-genres [[ 'genres', genre_id, 'subgenres', { 'from': 0, 'to': 48 }, ['id', 'name'] ]]) call_args = {'paths': paths} path_response = self.netflix_session._path_request(**call_args) return LoLoMo(path_response)
def req_episodes(self, videoid, perpetual_range_start=None): """Retrieve the episodes of a season""" if videoid.mediatype != common.VideoId.SEASON: raise common.InvalidVideoId('Cannot request episode list for {}'.format(videoid)) common.debug('Requesting episode list for {}', videoid) paths = ([['seasons', videoid.seasonid, 'summary']] + build_paths(['seasons', videoid.seasonid, 'episodes', RANGE_SELECTOR], EPISODES_PARTIAL_PATHS) + build_paths(['videos', videoid.tvshowid], ART_PARTIAL_PATHS + [['title']])) call_args = { 'paths': paths, 'length_params': ['stdlist_wid', ['seasons', videoid.seasonid, 'episodes']], 'perpetual_range_start': perpetual_range_start } path_response = self.netflix_session._perpetual_path_request(**call_args) return EpisodeList(videoid, path_response)
def req_loco_list_root(self): """Retrieve root LoCo list""" # It is used to following cases: # - To get items for the main menu # (when 'loco_known'==True and loco_contexts is set, see MAIN_MENU_ITEMS in globals.py) # - To get list items for menus that have multiple contexts set to 'loco_contexts' like 'recommendations' menu common.debug('Requesting LoCo root lists') paths = ( [['loco', { 'from': 0, 'to': 50 }, "componentSummary"]] + # Titles of first 4 videos in each video list (needed only to show titles in the plot description) [[ 'loco', { 'from': 0, 'to': 50 }, { 'from': 0, 'to': 3 }, 'reference', ['title', 'summary'] ]] + # Art for the first video of each context list (needed only to add art to the menu item) build_paths(['loco', { 'from': 0, 'to': 50 }, 0, 'reference'], ART_PARTIAL_PATHS)) call_args = {'paths': paths} path_response = self.netflix_session._path_request(**call_args) return LoCo(path_response)
def req_lolomo_list_root(self): """Retrieve root LoLoMo list""" # It is used to display main menu and the menus with 'lolomo_contexts' specified, like 'recommendations' menu common.debug('Requesting root LoLoMo lists') paths = ( [[ 'lolomo', { 'from': 0, 'to': 40 }, ['displayName', 'context', 'id', 'index', 'length', 'genreId'] ]] + # Titles of first 4 videos in each video list [[ 'lolomo', { 'from': 0, 'to': 40 }, { 'from': 0, 'to': 3 }, 'reference', ['title', 'summary'] ]] + # Art for first video in each video list (will be displayed as video list art) build_paths([ 'lolomo', { 'from': 0, 'to': 40 }, { 'from': 0, 'to': 0 }, 'reference' ], ART_PARTIAL_PATHS)) call_args = {'paths': paths} path_response = self.netflix_session._path_request(**call_args) return LoLoMo(path_response)
def req_datatype_video_list_full(self, context_name, switch_profiles=False): """ Retrieve the FULL video list for a context name (no limits to the number of path requests) contains only minimal video info """ common.debug('Requesting the full video list for {}', context_name) paths = build_paths([context_name, 'az', RANGE_PLACEHOLDER], VIDEO_LIST_BASIC_PARTIAL_PATHS) call_args = { 'paths': paths, 'length_params': ['stdlist', [context_name, 'az']], 'perpetual_range_start': None, 'request_size': PATH_REQUEST_SIZE_MAX, 'no_limit_req': True } if switch_profiles: # Used only with library auto-update with the sync with Netflix "My List" enabled. # It may happen that the user browses the frontend with a different profile used by library sync, # and it could cause a wrong query request to nf server. # So we try to switch the profile, get My List items and restore previous # active profile in a "single call" to try perform the operations in a faster way. path_response = self.netflix_session._perpetual_path_request_switch_profiles( **call_args) else: path_response = self.netflix_session._perpetual_path_request( **call_args) return {} if not path_response else VideoListSorted( path_response, context_name, None, 'az')
def req_video_list_sorted(self, context_name, context_id=None, perpetual_range_start=None, menu_data=None): """Retrieve a video list sorted""" # This type of request allows to obtain more than ~40 results common.debug( 'Requesting video list sorted for context name: "{}", context id: "{}"', context_name, context_id) base_path = [context_name] response_type = 'stdlist' if context_id: base_path.append(context_id) response_type = 'stdlist_wid' # enum order: AZ|ZA|Suggested|Year # sort order the "mylist" is supported only in US country, the only way to query is use 'az' sort_order_types = [ 'az', 'za', 'su', 'yr' ] if not context_name == 'mylist' else ['az', 'az'] req_sort_order_type = sort_order_types[int( g.ADDON.getSettingInt( 'menu_sortorder_' + menu_data.get('initial_menu_id', menu_data['path'][1])))] base_path.append(req_sort_order_type) paths = build_paths(base_path + [RANGE_PLACEHOLDER], VIDEO_LIST_PARTIAL_PATHS) path_response = self.netflix_session._perpetual_path_request( paths, [response_type, base_path], perpetual_range_start) return VideoListSorted(path_response, context_name, context_id, req_sort_order_type)
def req_datatype_video_list_byid(self, video_ids, custom_partial_paths=None): """Retrieve a video list which contains the specified by video ids and return a CustomVideoList object""" common.debug('Requesting a video list for {} videos', video_ids) paths = build_paths(['videos', video_ids], custom_partial_paths if custom_partial_paths else VIDEO_LIST_PARTIAL_PATHS) path_response = self.netflix_session._path_request(paths) return CustomVideoList(path_response)
def req_video_list_supplemental(self, videoid, supplemental_type): """Retrieve a video list of supplemental type videos""" if videoid.mediatype != common.VideoId.SHOW and videoid.mediatype != common.VideoId.MOVIE: raise common.InvalidVideoId('Cannot request video list supplemental for {}'.format(videoid)) common.debug('Requesting video list supplemental of type "{}" for {}', supplemental_type, videoid) path = build_paths( ['videos', videoid.value, supplemental_type, {"from": 0, "to": 35}], TRAILER_PARTIAL_PATHS ) path_response = self.netflix_session._path_request(path) return VideoListSorted(path_response, 'videos', videoid.value, supplemental_type)
def req_seasons(self, videoid, perpetual_range_start): """Retrieve the seasons of a tv show""" if videoid.mediatype != common.VideoId.SHOW: raise common.InvalidVideoId('Cannot request season list for {}'.format(videoid)) common.debug('Requesting the seasons list for show {}', videoid) call_args = { 'paths': build_paths(['videos', videoid.tvshowid], SEASONS_PARTIAL_PATHS), 'length_params': ['stdlist_wid', ['videos', videoid.tvshowid, 'seasonList']], 'perpetual_range_start': perpetual_range_start } path_response = self.netflix_session._perpetual_path_request(**call_args) return SeasonList(videoid, path_response)
def req_video_list_search(self, search_term, perpetual_range_start=None): """Retrieve a video list by search term""" common.debug('Requesting video list by search term "{}"', search_term) base_path = ['search', 'byTerm', '|' + search_term, 'titles', MAX_PATH_REQUEST_SIZE] paths = ([base_path + [['id', 'name', 'requestId']]] + build_paths(base_path + [RANGE_SELECTOR, 'reference'], VIDEO_LIST_PARTIAL_PATHS)) call_args = { 'paths': paths, 'length_params': ['searchlist', ['search', 'byReference']], 'perpetual_range_start': perpetual_range_start } path_response = self.netflix_session._perpetual_path_request(**call_args) return SearchVideoList(path_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.netflix_session._path_request(path) common.merge_dicts(path_response, merged_response) if perpetual_range_selector: merged_response.update(perpetual_range_selector) return CustomVideoList(merged_response)
def req_video_list(self, list_id, perpetual_range_start=None): """Retrieve a video list""" # Some of this type of request have results fixed at ~40 from netflix # The 'length' tag never return to the actual total count of the elements common.debug('Requesting video list {}', list_id) paths = build_paths(['lists', list_id, RANGE_SELECTOR, 'reference'], VIDEO_LIST_PARTIAL_PATHS) call_args = { 'paths': paths, 'length_params': ['stdlist', ['lists', list_id]], 'perpetual_range_start': perpetual_range_start } path_response = self.netflix_session._perpetual_path_request(**call_args) return VideoList(path_response)
def req_loco_list_genre(self, genre_id): """Retrieve LoCo for the given genre""" common.debug('Requesting LoCo for genre {}', genre_id) # Todo: 20/06/2020 Currently make requests for genres raise this exception from netflix server # (errors visible only with jsonGraph enabled on path request): # Msg: No signature of method: api.Lolomo.getLolomoRequest() is applicable for argument types: # (java.util.ArrayList, null, java.lang.Boolean) values: [[jaw, jawEpisode, jawTrailer], null, false] # ErrCause: groovy.lang.MissingMethodException: No signature of method: api.Lolomo.getLolomoRequest() # is applicable for argument types: (java.util.ArrayList, null, java.lang.Boolean) # values: [[jaw, jawEpisode, jawTrailer], null, false] # For reference the PR to restore the functionality: https://github.com/CastagnaIT/plugin.video.netflix/pull/685 paths = ( [['genres', genre_id, 'name'] + ['genres', genre_id, 'rw', 'componentSummary'] + # Titles of first 4 videos in each video list (needed only to show titles in the plot description) [ 'genres', genre_id, 'rw', { 'from': 0, 'to': 48 }, { 'from': 0, 'to': 3 }, 'reference', ['title', 'summary'] ]] + # Art for the first video of each context list (needed only to add art to the menu item) build_paths([ 'genres', genre_id, 'rw', { 'from': 0, 'to': 48 }, 0, 'reference' ], ART_PARTIAL_PATHS) + # IDs and names of sub-genres [[ 'genres', 34399, 'subgenres', { 'from': 0, 'to': 30 }, ['id', 'name'] ]]) call_args = {'paths': paths} path_response = self.netflix_session._path_request(**call_args) return LoCo(path_response)