def search_menu(self): ''' Main search menu ''' from helperobjects import TitleItem menu_items = [ TitleItem( title=localize(30424), # New search... path=url_for('search_query'), art_dict=dict(thumb='DefaultAddonsSearch.png'), info_dict=dict(plot=localize(30425)), is_playable=False, ) ] history = self.read_history() for keywords in history: menu_items.append( TitleItem(title=keywords, path=url_for('search_query', keywords=keywords), art_dict=dict(thumb='DefaultAddonsSearch.png'), is_playable=False, context_menu=[ (localize(30030), 'RunPlugin(%s)' % url_for('remove_search', keywords=keywords)) ])) if history: menu_items.append( TitleItem( title=localize(30426), # Clear search history path=url_for('clear_search'), info_dict=dict(plot=localize(30427)), art_dict=dict(thumb='icons/infodialogs/uninstall.png'), is_playable=False, )) show_listing(menu_items, category=30031, cache=False)
def search(self, keywords=None, page=0, edit=False): """The VRT NU add-on Search functionality and results""" if keywords is None or edit is True: keywords = get_search_string(keywords) if not keywords: end_of_directory() return if edit is True: container_update(url_for('search_query', keywords=keywords)) return from apihelper import ApiHelper from utils import realpage page = realpage(page) self.add(keywords) search_items, sort, ascending, content = ApiHelper(self._favorites, self._resumepoints).list_search(keywords, page=page) if not search_items: ok_dialog(heading=localize(30135), message=localize(30136, keywords=keywords)) end_of_directory() return # Add 'More…' entry at the end from helperobjects import TitleItem if len(search_items) == get_setting_int('itemsperpage', default=50): search_items.append(TitleItem( label=colour(localize(30300)), # More… path=url_for('search_query', keywords=keywords, page=page + 1), art_dict=dict(thumb='DefaultAddonSearch.png'), info_dict={}, )) self._favorites.refresh(ttl=ttl('indirect')) show_listing(search_items, category=30032, sort=sort, ascending=ascending, content=content, cache=False)
def list_youtube(channels=None): ''' Construct a list of youtube ListItems, either for Live TV or the TV Guide listing ''' youtube_items = [] if not has_addon('plugin.video.youtube') or get_setting('showyoutube', 'true') == 'false': return youtube_items for channel in CHANNELS: if channels and channel.get('name') not in channels: continue context_menu = [] art_dict = dict() # Try to use the white icons for thumbnails (used for icons as well) if has_addon('resource.images.studios.white'): art_dict['thumb'] = 'resource://resource.images.studios.white/{studio}.png'.format(**channel) else: art_dict['thumb'] = 'DefaultTags.png' if channel.get('youtube'): path = channel.get('youtube') label = localize(30143, **channel) # Channel on YouTube # A single Live channel means it is the entry for channel's TV Show listing, so make it stand out if channels and len(channels) == 1: label = '[B]%s[/B]' % label plot = localize(30144, **channel) # Watch on YouTube # NOTE: Playcount is required to not have live streams as "Watched" info_dict = dict(title=label, plot=plot, studio=channel.get('studio'), mediatype='video', playcount=0) context_menu.append(( localize(30413), 'RunPlugin(%s)' % url_for('delete_cache', cache_file='channel.%s.json' % channel) )) else: # Not a playable channel continue youtube_items.append(TitleItem( title=label, path=path, art_dict=art_dict, info_dict=info_dict, context_menu=context_menu, is_playable=False, )) return youtube_items
def list_featured(self): """Construct a list of featured Listitems""" from data import FEATURED featured_items = [] for feature in self.localize_features(FEATURED): featured_name = feature.get('name') featured_items.append( TitleItem( label=featured_name, path=url_for('featured', feature=feature.get('id')), art_dict=dict(thumb='DefaultCountry.png'), info_dict=dict(plot='[B]%s[/B]' % feature.get('name'), studio='VRT'), )) return featured_items
def tvshow_to_listitem(self, tvshow, program, cache_file): ''' Return a ListItem based on a Suggests API result ''' label = self._metadata.get_label(tvshow) if program: context_menu, favorite_marker, _ = self._metadata.get_context_menu(tvshow, program, cache_file) label += favorite_marker return TitleItem( title=label, path=url_for('programs', program=program), art_dict=self._metadata.get_art(tvshow), info_dict=self._metadata.get_info_labels(tvshow), context_menu=context_menu, )
def list_categories(self): """Construct a list of category ListItems""" from webscraper import get_categories categories = get_categories() category_items = [] from data import CATEGORIES for category in self.localize_categories(categories, CATEGORIES): if get_setting_bool('showfanart', default=True): thumbnail = category.get('thumbnail', 'DefaultGenre.png') else: thumbnail = 'DefaultGenre.png' category_items.append(TitleItem( label=category.get('name'), path=url_for('categories', category=category.get('id')), art_dict=dict(thumb=thumbnail, icon='DefaultGenre.png'), info_dict=dict(plot='[B]%s[/B]' % category.get('name'), studio='VRT'), )) return category_items
def search(self, keywords=None, page=None): ''' The VRT NU add-on Search functionality and results ''' if keywords is None: keywords = get_search_string() if not keywords: end_of_directory() return from statichelper import realpage page = realpage(page) self.add(keywords) from apihelper import ApiHelper search_items, sort, ascending, content = ApiHelper( self._favorites, self._resumepoints).list_search(keywords, page=page) if not search_items: ok_dialog(heading=localize(30135), message=localize(30136, keywords=keywords)) end_of_directory() return # Add 'More...' entry at the end from helperobjects import TitleItem if len(search_items) == 50: search_items.append( TitleItem( title=localize(30300), path=url_for('search_query', keywords=keywords, page=page + 1), art_dict=dict(thumb='DefaultAddonSearch.png'), info_dict=dict(), )) self._favorites.refresh(ttl=60 * 60) show_listing(search_items, category=30032, sort=sort, ascending=ascending, content=content, cache=False)
def add_upnext(self, video_id): """Add Up Next url to Kodi Player""" # Reset vrtnu_resumepoints property set_property('vrtnu_resumepoints', None) url = url_for('play_upnext', video_id=video_id) self.update_position() self.update_total() if self.isPlaying() and self.total - self.last_pos < 1: log(3, '[PlayerInfo {id}] Add {url} to Kodi Playlist', id=self.thread_id, url=url) PlayList(1).add(url) else: log(3, '[PlayerInfo {id}] Add {url} to Kodi Player', id=self.thread_id, url=url) self.play(url)
def show_recent_menu(self, page=0, use_favorites=False): """The VRT NU add-on 'Most recent' and 'My most recent' listing menu""" # My favorites menus may need more up-to-date favorites self._favorites.refresh(ttl=ttl('direct' if use_favorites else 'indirect')) self._resumepoints.refresh(ttl=ttl('direct' if use_favorites else 'indirect')) page = realpage(page) episode_items, sort, ascending, content = self._apihelper.list_episodes(page=page, use_favorites=use_favorites, variety='recent') # Add 'More...' entry at the end if len(episode_items) == get_setting_int('itemsperpage', default=50): recent = 'favorites_recent' if use_favorites else 'recent' episode_items.append(TitleItem( label=colour(localize(30300)), path=url_for(recent, page=page + 1), art_dict=dict(thumb='DefaultRecentlyAddedEpisodes.png'), info_dict=dict(), )) show_listing(episode_items, category=30020, sort=sort, ascending=ascending, content=content, cache=False)
def send_epg(self): # pylint: disable=no-method-argument,no-self-use """ Return JSON-EPG formatted information to IPTV Manager. """ import re from collections import defaultdict from datetime import datetime from dateutil.tz import UTC from kodiutils import url_for from redbull import RedBullTV redbull = RedBullTV() epg = defaultdict(list) for item in redbull.get_epg().get('items'): if (item.get('start_time') and item.get('end_time') and re.match('\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{3}Z', item.get('start_time')) # pylint: disable=anomalous-backslash-in-string and re.match('\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{3}Z', item.get('end_time'))): # pylint: disable=anomalous-backslash-in-string epg['redbulltv'].append( dict(start=datetime.strptime( item.get('start_time'), "%Y-%m-%dT%H:%M:%S.%fZ").replace( tzinfo=UTC).isoformat(), stop=datetime.strptime( item.get('end_time'), "%Y-%m-%dT%H:%M:%S.%fZ").replace( tzinfo=UTC).isoformat(), title=item.get('title'), description=item.get('long_description'), subtitle=item.get('subheading'), genre='Sport', image=redbull.get_image_url(item.get('id'), item.get('resources'), 'landscape'), stream=url_for('play_uid', uid=item.get('id')))) else: log("Invalid start or end time for Red Bull item ID {uid}". format(uid=item.get('id'))) return dict(version=1, epg=epg)
def episode_to_listitem(self, episode, program, cache_file, titletype): ''' Return a ListItem based on a Search API result ''' label, sort, ascending = self._metadata.get_label(episode, titletype, return_sort=True) if program: context_menu, favorite_marker, watchlater_marker = self._metadata.get_context_menu(episode, program, cache_file) label += favorite_marker + watchlater_marker info_labels = self._metadata.get_info_labels(episode) info_labels['title'] = label return TitleItem( title=label, path=url_for('play_id', video_id=episode.get('videoId'), publication_id=episode.get('publicationId')), art_dict=self._metadata.get_art(episode), info_dict=info_labels, prop_dict=self._metadata.get_properties(episode), context_menu=context_menu, is_playable=True, ), sort, ascending
def episode_to_listitem(self, episode, program, cache_file, titletype): """Return a ListItem based on a Search API result""" label, sort, ascending = self._metadata.get_label(episode, titletype, return_sort=True) if program: context_menu, favorite_marker, watchlater_marker = self._metadata.get_context_menu(episode, program, cache_file) label += favorite_marker + watchlater_marker info_labels = self._metadata.get_info_labels(episode) # FIXME: Due to a bug in Kodi, ListItem.Title is used when Sort methods are used, not ListItem.Label info_labels['title'] = label return TitleItem( label=label, path=url_for('play_id', video_id=episode.get('videoId'), publication_id=episode.get('publicationId')), art_dict=self._metadata.get_art(episode), info_dict=info_labels, prop_dict=self._metadata.get_properties(episode), context_menu=context_menu, is_playable=True, ), sort, ascending
def list_categories(self): ''' Construct a list of category ListItems ''' categories = [] # Try the cache if it is fresh categories = get_cache('categories.json', ttl=7 * 24 * 60 * 60) # Try to scrape from the web if not categories: try: categories = self.get_categories() except Exception: # pylint: disable=broad-except categories = [] else: update_cache('categories.json', categories) # Use the cache anyway (better than hard-coded) if not categories: categories = get_cache('categories.json', ttl=None) # Fall back to internal hard-coded categories if all else fails from data import CATEGORIES if not categories: categories = CATEGORIES category_items = [] for category in self.localize_categories(categories, CATEGORIES): if get_setting('showfanart', 'true') == 'true': thumbnail = category.get('thumbnail', 'DefaultGenre.png') else: thumbnail = 'DefaultGenre.png' category_items.append(TitleItem( title=category.get('name'), path=url_for('categories', category=category.get('id')), art_dict=dict(thumb=thumbnail, icon='DefaultGenre.png'), info_dict=dict(plot='[B]%s[/B]' % category.get('name'), studio='VRT'), )) return category_items
def show_offline_menu(self, page=0, use_favorites=False): """The VRT NU add-on 'Soon offline' and 'My soon offline' listing menu""" # My favorites menus may need more up-to-date favorites self._favorites.refresh(ttl=ttl('direct' if use_favorites else 'indirect')) self._resumepoints.refresh(ttl=ttl('direct' if use_favorites else 'indirect')) page = realpage(page) items_per_page = get_setting_int('itemsperpage', default=50) sort_key = 'assetOffTime' episode_items, sort, ascending, content = self._apihelper.list_episodes(page=page, items_per_page=items_per_page, use_favorites=use_favorites, variety='offline', sort_key=sort_key) # Add 'More...' entry at the end if len(episode_items) == items_per_page: offline = 'favorites_offline' if use_favorites else 'offline' episode_items.append(TitleItem( label=localize(30300), path=url_for(offline, page=page + 1), art_dict=dict(thumb='DefaultYear.png'), info_dict=dict(), )) show_listing(episode_items, category=30022, sort=sort, ascending=ascending, content=content, cache=False)
def show_main_menu(self): ''' The VRT NU add-on main menu ''' # self._favorites.refresh(ttl=60 * 60) main_items = [] # Only add 'My favorites' when it has been activated if self._favorites.is_activated(): main_items.append( TitleItem( title=localize(30010), # My favorites path=url_for('favorites_menu'), art_dict=dict(thumb='DefaultFavourites.png'), info_dict=dict(plot=localize(30011)), )) main_items.extend([ TitleItem( title=localize(30012), # All programs path=url_for('programs'), art_dict=dict(thumb='DefaultMovieTitle.png'), info_dict=dict(plot=localize(30013))), TitleItem( title=localize(30014), # Categories path=url_for('categories'), art_dict=dict(thumb='DefaultGenre.png'), info_dict=dict(plot=localize(30015))), TitleItem( title=localize(30016), # Channels path=url_for('channels'), art_dict=dict(thumb='DefaultTags.png'), info_dict=dict(plot=localize(30017))), TitleItem( title=localize(30018), # Live TV path=url_for('livetv'), art_dict=dict(thumb='DefaultTVShows.png'), info_dict=dict(plot=localize(30019))), TitleItem( title=localize(30020), # Recent items path=url_for('recent'), art_dict=dict(thumb='DefaultRecentlyAddedEpisodes.png'), info_dict=dict(plot=localize(30021))), TitleItem( title=localize(30022), # Soon offline path=url_for('offline'), art_dict=dict(thumb='DefaultYear.png'), info_dict=dict(plot=localize(30023))), TitleItem( title=localize(30024), # Featured content path=url_for('featured'), art_dict=dict(thumb='DefaultCountry.png'), info_dict=dict(plot=localize(30025))), TitleItem( title=localize(30026), # TV guide path=url_for('tvguide'), art_dict=dict(thumb='DefaultAddonTvInfo.png'), info_dict=dict(plot=localize(30027))), TitleItem( title=localize(30028), # Search path=url_for('search'), art_dict=dict(thumb='DefaultAddonsSearch.png'), info_dict=dict(plot=localize(30029))), ]) show_listing(main_items, cache=False) # No category self._version_check()
def get_context_menu(self, api_data, program, cache_file): """Get context menu""" from addon import plugin favorite_marker = '' watchlater_marker = '' context_menu = [] # WATCH LATER if self._resumepoints.is_activated(): asset_id = self.get_asset_id(api_data) # VRT NU Search API if api_data.get('type') == 'episode': program_title = api_data.get('program') # VRT NU Schedule API (some are missing vrt.whatson-id) elif api_data.get('vrt.whatson-id') or api_data.get('startTime'): program_title = api_data.get('title') if asset_id is not None: # We need to ensure forward slashes are quoted program_title = to_unicode( quote_plus(from_unicode(program_title))) url = url_to_episode(api_data.get('url', '')) if self._resumepoints.is_watchlater(asset_id): extras = {} # If we are in a watchlater menu, move cursor down before removing a favorite if plugin.path.startswith('/resumepoints/watchlater'): extras = dict(move_down=True) # Unwatch context menu context_menu.append( (capitalize(localize(30402)), 'RunPlugin(%s)' % url_for('unwatchlater', asset_id=asset_id, title=program_title, url=url, **extras))) watchlater_marker = '[COLOR={highlighted}]ᶫ[/COLOR]' else: # Watch context menu context_menu.append( (capitalize(localize(30401)), 'RunPlugin(%s)' % url_for('watchlater', asset_id=asset_id, title=program_title, url=url))) # FOLLOW PROGRAM if self._favorites.is_activated(): # VRT NU Search API if api_data.get('type') == 'episode': program_title = api_data.get('program') program_type = api_data.get('programType') follow_suffix = localize( 30410) if program_type != 'oneoff' else '' # program follow_enabled = True # VRT NU Suggest API elif api_data.get('type') == 'program': program_title = api_data.get('title') follow_suffix = '' follow_enabled = True # VRT NU Schedule API (some are missing vrt.whatson-id) elif api_data.get('vrt.whatson-id') or api_data.get('startTime'): program_title = api_data.get('title') follow_suffix = localize(30410) # program follow_enabled = bool(api_data.get('url')) if follow_enabled and program: program_title = to_unicode( quote_plus(from_unicode(program_title)) ) # We need to ensure forward slashes are quoted if self._favorites.is_favorite(program): extras = {} # If we are in a favorites menu, move cursor down before removing a favorite if plugin.path.startswith('/favorites'): extras = dict(move_down=True) context_menu.append(( localize(30412, title=follow_suffix), # Unfollow 'RunPlugin(%s)' % url_for('unfollow', program=program, title=program_title, **extras))) favorite_marker = '[COLOR={highlighted}]ᵛ[/COLOR]' else: context_menu.append(( localize(30411, title=follow_suffix), # Follow 'RunPlugin(%s)' % url_for( 'follow', program=program, title=program_title))) # GO TO PROGRAM if api_data.get('programType') != 'oneoff' and program: if plugin.path.startswith( ('/favorites/offline', '/favorites/recent', '/offline', '/recent', '/resumepoints/continue', '/resumepoints/watchlater', '/tvguide')): context_menu.append(( localize(30417), # Go to program 'Container.Update(%s)' % url_for('programs', program=program, season='allseasons'))) # REFRESH MENU context_menu.append(( localize(30413), # Refresh menu 'RunPlugin(%s)' % url_for('delete_cache', cache_file=cache_file))) return context_menu, colour(favorite_marker), colour(watchlater_marker)
def list_channels(self, channels=None, live=True): ''' Construct a list of channel ListItems, either for Live TV or the TV Guide listing ''' from tvguide import TVGuide _tvguide = TVGuide() channel_items = [] for channel in CHANNELS: if channels and channel.get('name') not in channels: continue context_menu = [] art_dict = dict() # Try to use the white icons for thumbnails (used for icons as well) if has_addon('resource.images.studios.white'): art_dict['thumb'] = 'resource://resource.images.studios.white/{studio}.png'.format(**channel) else: art_dict['thumb'] = 'DefaultTags.png' if not live: path = url_for('channels', channel=channel.get('name')) label = channel.get('label') plot = '[B]%s[/B]' % channel.get('label') is_playable = False info_dict = dict(title=label, plot=plot, studio=channel.get('studio'), mediatype='video') stream_dict = [] elif channel.get('live_stream') or channel.get('live_stream_id'): if channel.get('live_stream_id'): path = url_for('play_id', video_id=channel.get('live_stream_id')) elif channel.get('live_stream'): path = url_for('play_url', video_url=channel.get('live_stream')) label = localize(30141, **channel) # Channel live playing_now = _tvguide.playing_now(channel.get('name')) if playing_now: label += ' [COLOR yellow]| %s[/COLOR]' % playing_now # A single Live channel means it is the entry for channel's TV Show listing, so make it stand out if channels and len(channels) == 1: label = '[B]%s[/B]' % label is_playable = True if channel.get('name') in ['een', 'canvas', 'ketnet']: if get_setting('showfanart', 'true') == 'true': art_dict['fanart'] = self.get_live_screenshot(channel.get('name', art_dict.get('fanart'))) plot = '%s\n\n%s' % (localize(30142, **channel), _tvguide.live_description(channel.get('name'))) else: plot = localize(30142, **channel) # Watch live # NOTE: Playcount is required to not have live streams as "Watched" info_dict = dict(title=label, plot=plot, studio=channel.get('studio'), mediatype='video', playcount=0, duration=0) stream_dict = dict(duration=0) context_menu.append(( localize(30413), 'RunPlugin(%s)' % url_for('delete_cache', cache_file='channel.%s.json' % channel) )) else: # Not a playable channel continue channel_items.append(TitleItem( title=label, path=path, art_dict=art_dict, info_dict=info_dict, stream_dict=stream_dict, context_menu=context_menu, is_playable=is_playable, )) return channel_items
def __map_seasons(self, program, seasons, episodes): import random season_items = [] sort = 'label' ascending = True content = 'files' episode = random.choice(episodes) program_type = episode.get('programType') # Reverse sort seasons if program_type is 'reeksaflopend' or 'daily' if program_type in ('daily', 'reeksaflopend'): ascending = False # Add an "* All seasons" list item if get_global_setting('videolibrary.showallitems') is True: season_items.append( TitleItem( label=localize(30133), # All seasons path=url_for('programs', program=program, season='allseasons'), art_dict=self._metadata.get_art(episode, season='allseasons'), info_dict=dict( tvshowtitle=self._metadata.get_tvshowtitle(episode), plot=self._metadata.get_plot(episode, season='allseasons'), plotoutline=self._metadata.get_plotoutline( episode, season='allseasons'), tagline=self._metadata.get_plotoutline( episode, season='allseasons'), mediatype=self._metadata.get_mediatype( episode, season='allseasons'), studio=self._metadata.get_studio(episode), tag=self._metadata.get_tag(episode)), )) # NOTE: Sort the episodes ourselves, because Kodi does not allow to set to 'ascending' seasons = sorted(seasons, key=lambda k: k['key'], reverse=not ascending) for season in seasons: season_key = season.get('key', '') # If more than 300 episodes exist, we may end up with an empty season (Winteruur) try: episode = random.choice( [e for e in episodes if e.get('seasonName') == season_key]) except IndexError: episode = episodes[0] season_items.append( TitleItem( label=self._metadata.get_title(episode, season=season_key), path=url_for('programs', program=program, season=season_key), art_dict=self._metadata.get_art(episode, season=season_key), info_dict=self._metadata.get_info_labels( episode, season=season_key), prop_dict=self._metadata.get_properties(episode), )) return season_items, sort, ascending, content
def show_favorites_menu(self): """The VRT NU addon 'My programs' menu""" self._favorites.refresh(ttl=ttl('indirect')) favorites_items = [ TitleItem(label=localize(30040), # My programs path=url_for('favorites_programs'), art_dict=dict(thumb='DefaultMovieTitle.png'), info_dict=dict(plot=localize(30041))), TitleItem(label=localize(30048), # My recent items path=url_for('favorites_recent'), art_dict=dict(thumb='DefaultRecentlyAddedEpisodes.png'), info_dict=dict(plot=localize(30049))), TitleItem(label=localize(30050), # My soon offline path=url_for('favorites_offline'), art_dict=dict(thumb='DefaultYear.png'), info_dict=dict(plot=localize(30051))), ] # Only add 'My watch later' and 'Continue watching' when it has been activated if self._resumepoints.is_activated(): favorites_items.append(TitleItem( label=localize(30052), # My watch later path=url_for('resumepoints_watchlater'), art_dict=dict(thumb='DefaultVideoPlaylists.png'), info_dict=dict(plot=localize(30053)), )) favorites_items.append(TitleItem( label=localize(30054), # Continue Watching path=url_for('resumepoints_continue'), art_dict=dict(thumb='DefaultInProgressShows.png'), info_dict=dict(plot=localize(30055)), )) if get_setting_bool('addmymovies', default=True): favorites_items.append( TitleItem(label=localize(30042), # My movies path=url_for('categories', category='films'), art_dict=dict(thumb='DefaultAddonVideo.png'), info_dict=dict(plot=localize(30043))), ) if get_setting_bool('addmydocu', default=True): favorites_items.append( TitleItem(label=localize(30044), # My documentaries path=url_for('favorites_docu'), art_dict=dict(thumb='DefaultMovies.png'), info_dict=dict(plot=localize(30045))), ) if get_setting_bool('addmymusic', default=True): favorites_items.append( TitleItem(label=localize(30046), # My music path=url_for('favorites_music'), art_dict=dict(thumb='DefaultAddonMusic.png'), info_dict=dict(plot=localize(30047))), ) show_listing(favorites_items, category=30010, cache=False) # My favorites # Show dialog when no favorites were found if not self._favorites.titles(): ok_dialog(heading=localize(30415), message=localize(30416))