def show_main_menu(self): """The VRT NU add-on main menu""" # self._favorites.refresh(ttl=ttl('indirect')) main_items = [] # Only add 'My favorites' when it has been activated if self._favorites.is_activated(): main_items.append(TitleItem( label=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(label=localize(30012), # All programs path=url_for('programs'), art_dict=dict(thumb='DefaultMovieTitle.png'), info_dict=dict(plot=localize(30013))), TitleItem(label=localize(30014), # Categories path=url_for('categories'), art_dict=dict(thumb='DefaultGenre.png'), info_dict=dict(plot=localize(30015))), TitleItem(label=localize(30016), # Channels path=url_for('channels'), art_dict=dict(thumb='DefaultTags.png'), info_dict=dict(plot=localize(30017))), TitleItem(label=localize(30018), # Live TV path=url_for('livetv'), art_dict=dict(thumb='DefaultTVShows.png'), info_dict=dict(plot=localize(30019))), TitleItem(label=localize(30020), # Recent items path=url_for('recent'), art_dict=dict(thumb='DefaultRecentlyAddedEpisodes.png'), info_dict=dict(plot=localize(30021))), TitleItem(label=localize(30022), # Soon offline path=url_for('offline'), art_dict=dict(thumb='DefaultYear.png'), info_dict=dict(plot=localize(30023))), TitleItem(label=localize(30024), # Featured content path=url_for('featured'), art_dict=dict(thumb='DefaultCountry.png'), info_dict=dict(plot=localize(30025))), TitleItem(label=localize(30026), # TV guide path=url_for('tvguide'), art_dict=dict(thumb='DefaultAddonTvInfo.png'), info_dict=dict(plot=localize(30027))), TitleItem(label=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 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 show_offline_menu(self, page=0, use_favorites=False): ''' The VRT NU add-on 'Soon offline' and 'My soon offline' listing menu ''' from statichelper import realpage # My favorites menus may need more up-to-date favorites self._favorites.refresh(ttl=5 * 60 if use_favorites else 60 * 60) self._resumepoints.refresh(ttl=5 * 60 if use_favorites else 60 * 60) page = realpage(page) episode_items, sort, ascending, content = self._apihelper.list_episodes( page=page, use_favorites=use_favorites, variety='offline') # Add 'More...' entry at the end if len(episode_items) == 50: if use_favorites: offline = 'favorites_offline' else: offline = 'offline' episode_items.append( TitleItem( title=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 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_featured(self, online=False): """Construct a list of featured Listitems""" featured = [] if online: featured = self.get_featured_from_api() else: from data import FEATURED # Add VRT NU website featured items featured.extend(self.get_featured_from_web()) # Add hardcoded VRT Search API featured items for feature in self.localize_features(FEATURED): featured.append(feature) featured_items = [] for feature in 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 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 get_episode_items(self, date, channel): """Show episodes for a given date and channel""" now = datetime.now(dateutil.tz.tzlocal()) epg = self.parse(date, now) epg_url = epg.strftime(self.VRT_TVGUIDE) self._favorites.refresh(ttl=ttl('indirect')) self._resumepoints.refresh(ttl=ttl('indirect')) cache_file = 'schedule.{date}.json'.format(date=date) if date in ('today', 'yesterday', 'tomorrow'): schedule = get_cached_url_json(url=epg_url, cache=cache_file, ttl=ttl('indirect'), fail={}) else: schedule = get_url_json(url=epg_url, fail={}) entry = find_entry(CHANNELS, 'name', channel) if entry: episodes = schedule.get(entry.get('id'), []) else: episodes = [] episode_items = [] for episode in episodes: program = url_to_program(episode.get('url', '')) if episode.get('url'): video_url = add_https_proto(episode.get('url')) path = url_for('play_url', video_url=video_url) context_menu, favorite_marker, watchlater_marker = self._metadata.get_context_menu( episode, program, cache_file) label = self._metadata.get_label( episode) + favorite_marker + watchlater_marker is_playable = True else: label = '[COLOR={greyedout}]%s[/COLOR]' % self._metadata.get_label( episode) path = url_for('noop') context_menu, _, _ = self._metadata.get_context_menu( episode, program, cache_file) is_playable = False info_labels = self._metadata.get_info_labels(episode, date=date, channel=entry) # FIXME: Due to a bug in Kodi, ListItem.Title is used when Sort methods are used, not ListItem.Label info_labels['title'] = colour(label) episode_items.append( TitleItem( label=colour(label), path=path, art_dict=self._metadata.get_art(episode), info_dict=info_labels, context_menu=context_menu, is_playable=is_playable, )) return episode_items
def show_favorites_menu(self): ''' The VRT NU addon 'My programs' menu ''' self._favorites.refresh(ttl=60 * 60) favorites_items = [ TitleItem( title=localize(30040), # My programs path=url_for('favorites_programs'), art_dict=dict(thumb='DefaultMovieTitle.png'), info_dict=dict(plot=localize(30041))), TitleItem( title=localize(30046), # My recent items path=url_for('favorites_recent'), art_dict=dict(thumb='DefaultRecentlyAddedEpisodes.png'), info_dict=dict(plot=localize(30047))), TitleItem( title=localize(30048), # My soon offline path=url_for('favorites_offline'), art_dict=dict(thumb='DefaultYear.png'), info_dict=dict(plot=localize(30049))), ] # Only add 'My watch later' and 'Continue watching' when it has been activated if self._resumepoints.is_activated(): favorites_items.append( TitleItem( title=localize(30050), # My watch later path=url_for('resumepoints_watchlater'), art_dict=dict(thumb='DefaultVideoPlaylists.png'), info_dict=dict(plot=localize(30051)), )) favorites_items.append( TitleItem( title=localize(30052), # Continue Watching path=url_for('resumepoints_continue'), art_dict=dict(thumb='DefaultInProgressShows.png'), info_dict=dict(plot=localize(30053)), )) if get_setting('addmymovies', 'true') == 'true': favorites_items.append( TitleItem( title=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('addmydocu', 'true') == 'true': favorites_items.append( TitleItem( title=localize(30044), # My documentaries path=url_for('favorites_docu'), art_dict=dict(thumb='DefaultMovies.png'), info_dict=dict(plot=localize(30045))), ) 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))
def __map_seasons(self, program, seasons, episodes): import random season_items = [] sort = 'label' ascending = True content = 'seasons' episode = random.choice(episodes) info_labels = self._metadata.get_info_labels(episode, season=True) 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( title=localize(30133), path=url_for('programs', program=program, season='allseasons'), art_dict=self._metadata.get_art(episode, season='allseasons'), info_dict=info_labels, )) # 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', '') try: # If more than 300 episodes exist, we may end up with an empty season (Winteruur) episode = random.choice([e for e in episodes if e.get('seasonName') == season_key]) except IndexError: episode = episodes[0] label = '%s %s' % (localize(30131), season_key) season_items.append(TitleItem( title=label, path=url_for('programs', program=program, season=season_key), art_dict=self._metadata.get_art(episode, season=True), info_dict=info_labels, prop_dict=self._metadata.get_properties(episode), )) return season_items, sort, ascending, content
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 not get_setting_bool( 'showyoutube', default=True): return youtube_items for channel in CHANNELS: if channels and channel.get('name') not in channels: continue art_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' for youtube in channel.get('youtube', []): path = youtube_to_plugin_url(youtube['url']) label = localize(30143, **youtube) # 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, **youtube) # 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 = [( localize(30413), # Refresh menu 'RunPlugin(%s)' % url_for('delete_cache', cache_file='channel.{channel}.json'.format( channel=channel)), )] youtube_items.append( TitleItem( label=label, path=path, art_dict=art_dict, info_dict=info_dict, context_menu=context_menu, is_playable=False, )) return youtube_items
def get_channel_items(self, date=None, channel=None): """Offer a menu to select the channel""" if date: now = datetime.now(dateutil.tz.tzlocal()) epg = self.parse(date, now) datelong = localize_datelong(epg) channel_items = [] for chan in CHANNELS: # Only some channels are supported if not chan.get('has_tvguide'): continue # If a channel is requested, stop processing if it is no match if channel and channel != chan.get('name'): continue art_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( **chan) else: art_dict['thumb'] = 'DefaultTags.png' if date: label = chan.get('label') path = url_for('tvguide', date=date, channel=chan.get('name')) plot = '[B]%s[/B]\n%s' % (datelong, localize(30302, **chan)) else: label = '[B]%s[/B]' % localize(30303, **chan) path = url_for('tvguide_channel', channel=chan.get('name')) plot = '%s\n\n%s' % (localize( 30302, **chan), self.live_description(chan.get('name'))) context_menu = [( localize(30413), # Refresh menu 'RunPlugin(%s)' % url_for('delete_cache', cache_file='channel.{channel}.json'.format( channel=chan.get('name'))), )] channel_items.append( TitleItem( label=label, path=path, art_dict=art_dict, context_menu=context_menu, info_dict=dict(plot=plot, studio=chan.get('studio')), )) return channel_items
def get_episode_items(self, date, channel): ''' Show episodes for a given date and channel ''' now = datetime.now(dateutil.tz.tzlocal()) epg = self.parse(date, now) epg_url = epg.strftime(self.VRT_TVGUIDE) self._favorites.refresh(ttl=60 * 60) cache_file = 'schedule.%s.json' % date if date in ('today', 'yesterday', 'tomorrow'): # Try the cache if it is fresh schedule = get_cache(cache_file, ttl=60 * 60) if not schedule: from json import load log(2, 'URL get: {url}', url=epg_url) schedule = load(urlopen(epg_url)) update_cache(cache_file, schedule) else: from json import load log(2, 'URL get: {url}', url=epg_url) schedule = load(urlopen(epg_url)) entry = find_entry(CHANNELS, 'name', channel) if entry: episodes = schedule.get(entry.get('id'), []) else: episodes = [] episode_items = [] for episode in episodes: label = self._metadata.get_label(episode) context_menu = [] path = None if episode.get('url'): from statichelper import add_https_method, url_to_program video_url = add_https_method(episode.get('url')) path = url_for('play_url', video_url=video_url) program = url_to_program(episode.get('url')) 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, date=date, channel=entry) info_labels['title'] = label episode_items.append(TitleItem( title=label, path=path, art_dict=self._metadata.get_art(episode), info_dict=info_labels, is_playable=True, context_menu=context_menu, )) return episode_items
def get_single_episode(self, video_id=None, whatson_id=None, video_url=None): """Get single episode by videoId, whatsonId or url""" video = None episode = self.get_single_episode_data(video_id=video_id, whatson_id=whatson_id, video_url=video_url) if episode: video_item = TitleItem( label=self._metadata.get_label(episode), art_dict=self._metadata.get_art(episode), info_dict=self._metadata.get_info_labels(episode), prop_dict=self._metadata.get_properties(episode), ) video = dict(listitem=video_item, video_id=episode.get('videoId'), publication_id=episode.get('publicationId')) return video
def search_menu(self): """Main search menu""" from helperobjects import TitleItem menu_items = [ TitleItem( label=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( label=keywords, path=url_for('search_query', keywords=keywords), is_playable=False, context_menu=[( localize(30033), # Edit 'RunPlugin(%s)' % url_for('edit_search', keywords=keywords), ), ( localize(30030), # Remove 'RunPlugin(%s)' % url_for('remove_search', keywords=keywords), )], )) if history: menu_items.append(TitleItem( label=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 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( title=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 get_single_episode(self, whatson_id): ''' Get single episode by whatsonId ''' video = None api_data = self.get_episodes(whatson_id=whatson_id, variety='single') if len(api_data) == 1: episode = api_data[0] video_item = TitleItem( title=self._metadata.get_label(episode), art_dict=self._metadata.get_art(episode), info_dict=self._metadata.get_info_labels(episode), prop_dict=self._metadata.get_properties(episode), ) video = dict(listitem=video_item, video_id=episode.get('videoId'), publication_id=episode.get('publicationId')) return video
def get_date_items(channel=None): """Offer a menu to select the TV-guide date""" epg = datetime.now(dateutil.tz.tzlocal()) # Daily EPG information shows information from 6AM until 6AM if epg.hour < 6: epg += timedelta(days=-1) date_items = [] for offset in range(14, -19, -1): day = epg + timedelta(days=offset) label = localize_datelong(day) date = day.strftime('%Y-%m-%d') # Highlight today with context of 2 days entry = find_entry(RELATIVE_DATES, 'offset', offset) if entry: date_name = localize(entry.get('msgctxt')) if entry.get('permalink'): date = entry.get('id') if offset == 0: label = '[COLOR={highlighted}][B]{name}[/B], {date}[/COLOR]'.format( highlighted=themecolour('highlighted'), name=date_name, date=label) else: label = '[B]{name}[/B], {date}'.format(name=date_name, date=label) plot = '[B]{datelong}[/B]'.format(datelong=localize_datelong(day)) # Show channel list or channel episodes if channel: path = url_for('tvguide', date=date, channel=channel) else: path = url_for('tvguide', date=date) cache_file = 'schedule.{date}.json'.format(date=date) date_items.append( TitleItem( label=label, path=path, art_dict=dict(thumb='DefaultYear.png'), info_dict=dict(plot=plot), context_menu=[( localize(30413), # Refresh menu 'RunPlugin(%s)' % url_for('delete_cache', cache_file=cache_file))], )) return date_items
def get_latest_episode(self, program): ''' Get the latest episode of a program ''' api_data = self.get_episodes(program=program, variety='single') if len(api_data) != 1: return None episode = api_data[0] log(2, str(episode)) video_item = TitleItem( title=self._metadata.get_label(episode), art_dict=self._metadata.get_art(episode), info_dict=self._metadata.get_info_labels(episode), prop_dict=self._metadata.get_properties(episode), ) video = dict(listitem=video_item, video_id=episode.get('videoId'), publication_id=episode.get('publicationId')) return video
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 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 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 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_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 get_episode_by_air_date(self, channel_name, start_date, end_date=None): ''' Get an episode of a program given the channel and the air date in iso format (2019-07-06T19:35:00) ''' channel = statichelper.find_entry(CHANNELS, 'name', channel_name) if not channel: return None from datetime import datetime, timedelta import dateutil.parser import dateutil.tz offairdate = None try: onairdate = dateutil.parser.parse(start_date, default=datetime.now(dateutil.tz.gettz('Europe/Brussels'))) except ValueError: return None if end_date: try: offairdate = dateutil.parser.parse(end_date, default=datetime.now(dateutil.tz.gettz('Europe/Brussels'))) except ValueError: return None video = None episode_guess_off = None now = datetime.now(dateutil.tz.gettz('Europe/Brussels')) if onairdate.hour < 6: schedule_date = onairdate - timedelta(days=1) else: schedule_date = onairdate schedule_datestr = schedule_date.isoformat().split('T')[0] url = 'https://www.vrt.be/bin/epg/schedule.%s.json' % schedule_datestr from json import load schedule_json = load(urlopen(url)) episodes = schedule_json.get(channel.get('id'), []) if not episodes: return None if offairdate: mindate = min(abs(offairdate - dateutil.parser.parse(episode.get('endTime'))) for episode in episodes) episode_guess_off = next((episode for episode in episodes if abs(offairdate - dateutil.parser.parse(episode.get('endTime'))) == mindate), None) mindate = min(abs(onairdate - dateutil.parser.parse(episode.get('startTime'))) for episode in episodes) episode_guess_on = next((episode for episode in episodes if abs(onairdate - dateutil.parser.parse(episode.get('startTime'))) == mindate), None) offairdate_guess = dateutil.parser.parse(episode_guess_on.get('endTime')) if (episode_guess_off and episode_guess_on.get('vrt.whatson-id') == episode_guess_off.get('vrt.whatson-id') or (not episode_guess_off and episode_guess_on)): video = self.get_single_episode(episode_guess_on.get('vrt.whatson-id')) if video: return video # Airdate live2vod feature: use livestream cache of last 24 hours if no video was found if now - timedelta(hours=24) <= dateutil.parser.parse(episode_guess_on.get('endTime')) <= now: start_date = onairdate.astimezone(dateutil.tz.UTC).isoformat()[0:19] end_date = offairdate_guess.astimezone(dateutil.tz.UTC).isoformat()[0:19] # Offairdate defined if offairdate and now - timedelta(hours=24) <= offairdate <= now: start_date = onairdate.astimezone(dateutil.tz.UTC).isoformat()[0:19] end_date = offairdate.astimezone(dateutil.tz.UTC).isoformat()[0:19] if start_date and end_date: video_item = TitleItem( title=self._metadata.get_label(episode_guess_on), art_dict=self._metadata.get_art(episode_guess_on), info_dict=self._metadata.get_info_labels(episode_guess_on, channel=channel, date=start_date), prop_dict=self._metadata.get_properties(episode_guess_on), ) video = dict( listitem=video_item, video_id=channel.get('live_stream_id'), start_date=start_date, end_date=end_date, ) return video video = dict( errorlabel=episode_guess_on.get('title') ) return video
def get_episode_by_air_date(self, channel_name, start_date, end_date=None): """Get an episode of a program given the channel and the air date in iso format (2019-07-06T19:35:00)""" channel = find_entry(CHANNELS, 'name', channel_name) if not channel: return None from datetime import datetime, timedelta import dateutil.parser import dateutil.tz offairdate = None try: onairdate = dateutil.parser.parse( start_date, default=datetime.now(dateutil.tz.gettz('Europe/Brussels'))) except ValueError: return None if end_date: try: offairdate = dateutil.parser.parse( end_date, default=datetime.now(dateutil.tz.gettz('Europe/Brussels'))) except ValueError: return None video = None now = datetime.now(dateutil.tz.gettz('Europe/Brussels')) if onairdate.hour < 6: schedule_date = onairdate - timedelta(days=1) else: schedule_date = onairdate schedule_datestr = schedule_date.isoformat().split('T')[0] url = 'https://www.vrt.be/bin/epg/schedule.{date}.json'.format( date=schedule_datestr) schedule_json = get_url_json(url, fail={}) episodes = schedule_json.get(channel.get('id'), []) if not episodes: return None # Guess the episode episode_guess = None if not offairdate: mindate = min( abs(onairdate - dateutil.parser.parse(episode.get('startTime'))) for episode in episodes) episode_guess = next((episode for episode in episodes if abs( onairdate - dateutil.parser.parse(episode.get('startTime'))) == mindate), None) else: duration = offairdate - onairdate midairdate = onairdate + timedelta( seconds=duration.total_seconds() / 2) mindate = min( abs(midairdate - (dateutil.parser.parse(episode.get('startTime')) + timedelta(seconds=(dateutil.parser.parse( episode.get('endTime')) - dateutil.parser.parse( episode.get('startTime'))).total_seconds() / 2))) for episode in episodes) episode_guess = next((episode for episode in episodes if abs( midairdate - (dateutil.parser.parse(episode.get('startTime')) + timedelta( seconds=(dateutil.parser.parse(episode.get('endTime')) - dateutil.parser.parse(episode.get('startTime')) ).total_seconds() / 2))) == mindate), None) if episode_guess and episode_guess.get('vrt.whatson-id', None): offairdate_guess = dateutil.parser.parse( episode_guess.get('endTime')) video = self.get_single_episode( whatson_id=episode_guess.get('vrt.whatson-id')) if video: return video # Airdate live2vod feature: use livestream cache of last 24 hours if no video was found if now - timedelta(hours=24) <= dateutil.parser.parse( episode_guess.get('endTime')) <= now: start_date = onairdate.astimezone( dateutil.tz.UTC).isoformat()[0:19] end_date = offairdate_guess.astimezone( dateutil.tz.UTC).isoformat()[0:19] # Offairdate defined if offairdate and now - timedelta(hours=24) <= offairdate <= now: start_date = onairdate.astimezone( dateutil.tz.UTC).isoformat()[:19] end_date = offairdate.astimezone( dateutil.tz.UTC).isoformat()[:19] if start_date and end_date: info = self._metadata.get_info_labels(episode_guess, channel=channel, date=start_date) live2vod_title = '{} ({})'.format( info.get('tvshowtitle'), localize(30454)) # from livestream cache info.update(tvshowtitle=live2vod_title) video_item = TitleItem( label=self._metadata.get_label(episode_guess), art_dict=self._metadata.get_art(episode_guess), info_dict=info, prop_dict=self._metadata.get_properties(episode_guess), ) video = dict( listitem=video_item, video_id=channel.get('live_stream_id'), start_date=start_date, end_date=end_date, ) return video video = dict(errorlabel=episode_guess.get('title')) return video
def get_episode_items(self, date, channel): """Show episodes for a given date and channel""" now = datetime.now(dateutil.tz.tzlocal()) epg = self.parse(date, now) epg_url = epg.strftime(self.VRT_TVGUIDE) self._favorites.refresh(ttl=ttl('indirect')) self._resumepoints.refresh(ttl=ttl('indirect')) cache_file = 'schedule.{date}.json'.format(date=date) if date in ('today', 'yesterday', 'tomorrow'): schedule = get_cached_url_json(url=epg_url, cache=cache_file, ttl=ttl('indirect'), fail={}) else: schedule = get_url_json(url=epg_url, fail={}) entry = find_entry(CHANNELS, 'name', channel) if entry: episodes = schedule.get(entry.get('id'), []) else: episodes = [] episode_items = [] for episode in episodes: program = url_to_program(episode.get('url', '')) context_menu, favorite_marker, watchlater_marker = self._metadata.get_context_menu( episode, program, cache_file) label = self._metadata.get_label(episode) path = self.get_episode_path(episode, channel) # Playable item if '/play/' in path: is_playable = True label += favorite_marker + watchlater_marker # Non-actionable item else: is_playable = False label = '[COLOR={greyedout}]%s[/COLOR]' % label # Now playing start_date = dateutil.parser.parse(episode.get('startTime')) end_date = dateutil.parser.parse(episode.get('endTime')) if start_date <= now <= end_date: if is_playable: label = '[COLOR={highlighted}]%s[/COLOR] %s' % ( label, localize(30301)) else: label += localize(30301) info_labels = self._metadata.get_info_labels(episode, date=date, channel=entry) # FIXME: Due to a bug in Kodi, ListItem.Title is used when Sort methods are used, not ListItem.Label info_labels['title'] = colour(label) episode_items.append( TitleItem( label=colour(label), path=path, art_dict=self._metadata.get_art(episode), info_dict=info_labels, context_menu=context_menu, is_playable=is_playable, )) return episode_items