Esempio n. 1
0
    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_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 live_description(self, channel):
        """Return the EPG information for current and next live program"""
        now = datetime.now(dateutil.tz.tzlocal())
        epg = now
        # Daily EPG information shows information from 6AM until 6AM
        if epg.hour < 6:
            epg += timedelta(days=-1)

        entry = find_entry(CHANNELS, 'name', channel)
        if not entry:
            return ''

        epg_url = epg.strftime(self.VRT_TVGUIDE)
        schedule = get_cached_url_json(url=epg_url,
                                       cache='schedule.today.json',
                                       ttl=ttl('indirect'),
                                       fail={})
        episodes = iter(schedule.get(entry.get('id'), []))

        description = ''
        episode = None
        while True:
            try:
                episode = next(episodes)
            except StopIteration:
                break
            start_date = dateutil.parser.parse(episode.get('startTime'))
            end_date = dateutil.parser.parse(episode.get('endTime'))
            if start_date <= now <= end_date:  # Now playing
                description = '[COLOR={highlighted}][B]%s[/B] %s[/COLOR]\n' % (
                    localize(30421), self.episode_description(episode))
                try:
                    description += '[B]%s[/B] %s' % (localize(30422),
                                                     self.episode_description(
                                                         next(episodes)))
                except StopIteration:
                    break
                break
            if now < start_date:  # Nothing playing now, but this may be next
                description = '[B]%s[/B] %s\n' % (
                    localize(30422), self.episode_description(episode))
                try:
                    description += '[B]%s[/B] %s' % (localize(30422),
                                                     self.episode_description(
                                                         next(episodes)))
                except StopIteration:
                    break
                break
        if episode and not description:
            # Add a final 'No transmission' program
            description = '[COLOR={highlighted}][B]%s[/B] %s - 06:00\n» %s[/COLOR]' % (
                localize(30421), episode.get('end'), localize(30423))
        return colour(description)
    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 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
    def get_label(api_data, titletype=None, return_sort=False):
        """Get an appropriate label string matching the type of listing and VRT NU provided displayOptions from single item json api data"""

        # VRT NU Search API
        if api_data.get('type') == 'episode':
            display_options = api_data.get('displayOptions', {})

            # NOTE: Hard-code showing seasons because it is unreliable (i.e; Thuis or Down the Road have it disabled)
            display_options['showSeason'] = True

            program_type = api_data.get('programType')
            if not titletype:
                titletype = program_type

            if display_options.get('showEpisodeTitle'):
                label = html_to_kodi(
                    api_data.get('title', '')
                    or api_data.get('shortDescription', ''))
            elif display_options.get('showShortDescription'):
                label = html_to_kodi(
                    api_data.get('shortDescription', '')
                    or api_data.get('title', ''))
            else:
                label = html_to_kodi(
                    api_data.get('title', '')
                    or api_data.get('shortDescription', ''))

            sort = 'unsorted'
            ascending = True

            if titletype in ('continue', 'offline', 'recent', 'watchlater'):
                ascending = False
                label = '[B]%s[/B] - %s' % (api_data.get('program'), label)
                sort = 'dateadded'

            elif titletype in ('reeksaflopend', 'reeksoplopend'):

                if titletype == 'reeksaflopend':
                    ascending = False

                # NOTE: This is disable on purpose as 'showSeason' is not reliable
                if (display_options.get('showSeason') is False
                        and display_options.get('showEpisodeNumber')
                        and api_data.get('seasonName')
                        and api_data.get('episodeNumber')):
                    try:
                        label = 'S%02dE%02d: %s' % (
                            int(api_data.get('seasonName')),
                            int(api_data.get('episodeNumber')), label)
                    except ValueError:
                        # Season may not always be a perfect number
                        sort = 'episode'
                    else:
                        sort = 'dateadded'
                elif display_options.get('showEpisodeNumber') and api_data.get(
                        'episodeNumber') and ascending:
                    # NOTE: Do not prefix with "Episode X" when sorting by episode
                    # label = '%s %s: %s' % (localize(30132), api_data.get('episodeNumber'), label)
                    sort = 'episode'
                elif display_options.get('showBroadcastDate') and api_data.get(
                        'formattedBroadcastShortDate'):
                    label = '%s - %s' % (
                        api_data.get('formattedBroadcastShortDate'), label)
                    sort = 'dateadded'
                else:
                    sort = 'dateadded'

            elif titletype == 'daily':
                ascending = False
                label = '%s - %s' % (
                    api_data.get('formattedBroadcastShortDate'), label)
                sort = 'dateadded'

            elif titletype == 'oneoff':
                label = api_data.get('program', label)
                sort = 'label'

        # VRT NU Suggest API
        elif api_data.get('type') == 'program':
            label = api_data.get('title', '???')

        # VRT NU Schedule API (some are missing vrt.whatson-id)
        elif api_data.get('vrt.whatson-id') or api_data.get('startTime'):
            title = html_to_kodi(
                api_data.get('subtitle', '')
                or api_data.get('shortDescription', ''))
            label = '{start} - [B]{program}[/B]{title}'.format(
                start=api_data.get('start'),
                program=api_data.get('title'),
                title=' - ' + title if title else '',
            )

        # Not Found
        else:
            label = ''

        if return_sort:
            return colour(label), sort, ascending

        return colour(label)
    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 get_plot(self, api_data, season=False, date=None):
        """Get plot string from single item json api data"""
        from datetime import datetime
        import dateutil.parser
        import dateutil.tz

        # VRT NU Search API
        if api_data.get('type') == 'episode':
            if season is not False:
                plot = html_to_kodi(api_data.get('programDescription', ''))

                # Add additional metadata to plot
                plot_meta = ''
                if api_data.get('allowedRegion') == 'BE':
                    plot_meta += localize(30201) + '\n\n'  # Geo-blocked
                plot = '%s[B]%s[/B]\n%s' % (plot_meta, api_data.get('program'),
                                            plot)
                return colour(plot)

            # Add additional metadata to plot
            plot_meta = ''
            # Only display when a video disappears if it is within the next 3 months
            if api_data.get('assetOffTime'):
                offtime = dateutil.parser.parse(api_data.get('assetOffTime'))

                # Show the remaining days/hours the episode is still available
                if offtime:
                    now = datetime.now(dateutil.tz.tzlocal())
                    remaining = offtime - now
                    if remaining.days / 365 > 5:
                        pass  # If it is available for more than 5 years, do not show
                    elif remaining.days / 365 > 2:
                        plot_meta += localize(
                            30202, years=int(remaining.days /
                                             365))  # X years remaining
                    elif remaining.days / 30.5 > 3:
                        plot_meta += localize(
                            30203, months=int(remaining.days /
                                              30.5))  # X months remaining
                    elif remaining.days > 1:
                        plot_meta += localize(
                            30204, days=remaining.days)  # X days to go
                    elif remaining.days == 1:
                        plot_meta += localize(30205)  # 1 day to go
                    elif remaining.seconds // 3600 > 1:
                        plot_meta += localize(30206,
                                              hours=remaining.seconds //
                                              3600)  # X hours to go
                    elif remaining.seconds // 3600 == 1:
                        plot_meta += localize(30207)  # 1 hour to go
                    else:
                        plot_meta += localize(30208,
                                              minutes=remaining.seconds //
                                              60)  # X minutes to go

            if api_data.get('allowedRegion') == 'BE':
                if plot_meta:
                    plot_meta += '  '
                plot_meta += localize(30201)  # Geo-blocked

            # Add product placement
            if api_data.get('productPlacement') is True:
                if plot_meta:
                    plot_meta += '  '
                plot_meta += '[B]PP[/B]'

            # Add film rating
            rating = self.get_mpaa(api_data)
            if rating:
                if plot_meta:
                    plot_meta += '  '
                plot_meta += '[B]%s[/B]' % rating

            plot = html_to_kodi(api_data.get('description', ''))

            if plot_meta:
                plot = '%s\n\n%s' % (plot_meta, plot)

            permalink = shorten_link(
                api_data.get('permalink')) or api_data.get('externalPermalink')
            if permalink and get_setting_bool('showpermalink', default=False):
                plot = '%s\n\n[COLOR={highlighted}]%s[/COLOR]' % (plot,
                                                                  permalink)
            return colour(plot)

        # VRT NU Suggest API
        if api_data.get('type') == 'program':
            plot = unescape(api_data.get('description', '???'))
            # permalink = shorten_link(api_data.get('programUrl'))
            # if permalink and get_setting_bool('showpermalink', default=False):
            #     plot = '%s\n\n[COLOR={highlighted}]%s[/COLOR]' % (plot, permalink)
            return colour(plot)

        # VRT NU Schedule API (some are missing vrt.whatson-id)
        if api_data.get('vrt.whatson-id') or api_data.get('startTime'):
            now = datetime.now(dateutil.tz.tzlocal())
            epg = self.parse(date, now)
            plot = '[B]{datelong}[/B]\n{start} - {end}\n\n{description}'.format(
                datelong=localize_datelong(epg),
                start=api_data.get('start'),
                end=api_data.get('end'),
                description=html_to_kodi(api_data.get('description', '')),
            )
            return colour(plot)

        # Not Found
        return ''