def new_index():
    # New index will have the channels listed and then the buckets from the watch
    # web product
    refresh = arg_as_bool('refresh')
    clear_cache = arg_as_bool('clear-cache')
    adobe_activate_api.clean_up_authorization_tokens()
    if clear_cache:
        util.clear_cache(get_v3_url(WATCH_API_V3_LIVE))
        util.clear_cache(get_v3_url(WATCH_API_V3_WEB_HOME))

    parse_json(WATCH_API_V3_LIVE)
    addDirectoryItem(plugin.handle, plugin.url_for(search),
                     ListItem(get_string(40500)), True)
    parse_json(WATCH_API_V3_WEB_HOME)

    current_time = time.strftime("%I:%M %p", time.localtime(time.time()))
    addDirectoryItem(plugin.handle, plugin.url_for(new_index, refresh=True),
                     ListItem(get_string(30850) % current_time), True)
    addDirectoryItem(plugin.handle, plugin.url_for(index),
                     ListItem(get_string(30790)), True)

    endOfDirectory(plugin.handle,
                   succeeded=True,
                   updateListing=refresh,
                   cacheToDisc=False)
Exemple #2
0
def list_sports():
    espn_url = arg_as_string('espn_url')
    if 'action=replay' in espn_url:
        image = defaultreplay
    elif 'action=upcoming' in espn_url:
        image = defaultupcoming
    else:
        image = None
    addDirectoryItem(plugin.handle,
                     plugin.url_for(live_events_mode, espn_url=espn_url),
                     make_list_item(get_string(30034), icon=image), True)
    sports = []
    sport_elements = util.get_url_as_xml_cache(espn_url).findall(
        './/sportDisplayValue')
    for sport in sport_elements:
        sport = sport.text.encode('utf-8')
        if sport not in sports:
            sports.append(sport)
    for sport in sports:
        addDirectoryItem(
            plugin.handle,
            plugin.url_for(live_sport_events_mode,
                           sport=sport,
                           espn_url=espn_url), make_list_item(sport,
                                                              icon=image),
            True)

    xbmcplugin.addSortMethod(plugin.handle,
                             xbmcplugin.SORT_METHOD_VIDEO_SORT_TITLE)
    xbmcplugin.endOfDirectory(plugin.handle)
def search():
    search_settings.set_last_search_query('')
    addDirectoryItem(plugin.handle, plugin.url_for(search_input),
                     ListItem('[B]%s[/B]' % get_string(40501)), True)
    for search_history in search_settings.search_history:
        addDirectoryItem(plugin.handle,
                         plugin.url_for(search_results, q=search_history),
                         ListItem(search_history), True)
    endOfDirectory(plugin.handle, succeeded=True, cacheToDisc=False)
Exemple #4
0
def tvos_root_menu():
    page_api.parse_json(TV_OS_HOME)

    addDirectoryItem(plugin.handle,
                     plugin.url_for(page_api.page_api_url, url=TV_OS_SPORTS),
                     make_list_item(get_string(30550)), True)
    addDirectoryItem(plugin.handle,
                     plugin.url_for(page_api.page_api_url, url=TV_OS_CHANNELS),
                     make_list_item(get_string(30560)), True)
    endOfDirectory(plugin.handle)
def process_buckets(url,
                    header_bucket,
                    buckets,
                    selected_buckets,
                    current_bucket_path,
                    channel_filter=None,
                    was_search=False):
    selected_bucket = None if selected_buckets is None or len(
        selected_buckets) == 0 else selected_buckets[0]
    logging.debug('Selected buckets: %s Current Path: %s' %
                  (selected_buckets, current_bucket_path))
    original_bucket_path = current_bucket_path
    if header_bucket is not None and selected_bucket is None:
        index_bucket_content(url, header_bucket, channel_filter)
    for bucket in buckets:
        current_bucket_path = list(original_bucket_path)
        current_bucket_path.append(str(bucket['id']))
        if selected_bucket is not None and str(
                bucket['id']) != selected_bucket:
            continue
        if ('contents' in bucket or 'buckets'
                in bucket) and selected_bucket is None and len(buckets) > 1:
            if bucket.get('type', '') != 'images':
                bucket_path = '/'.join(current_bucket_path)
                if 'links' in bucket and 'self' in bucket[
                        'links'] and not was_search:
                    bucket_url = bucket['links']['self']
                    # bucket_path shouldn't be needed because we are using the full url to it
                    addDirectoryItem(
                        plugin.handle,
                        plugin.url_for(page_api_url_bucket,
                                       bucket_id=bucket['id'],
                                       url=bucket_url),
                        ListItem(bucket['name']), True)
                else:
                    # The items are listed directly in the bucket, not in a sub-url, so use the bucket_path
                    addDirectoryItem(
                        plugin.handle,
                        plugin.url_for(page_api_buckets,
                                       bucket_path=bucket_path,
                                       url=url,
                                       bucket_url=url),
                        ListItem(bucket['name']), True)
        else:
            logging.debug('Processing bucket %s' % bucket['id'])
            if 'buckets' in bucket:
                if selected_buckets is not None and len(selected_buckets) > 0:
                    process_buckets(url, None, bucket['buckets'],
                                    selected_buckets[1:], current_bucket_path)
                else:
                    process_buckets(url, None, bucket['buckets'], list(),
                                    current_bucket_path)
            else:
                index_bucket_content(url, bucket, channel_filter)
def index_v3_show(content):
    content_url = content['links']['self']
    name = content['name']
    fanart = content['imageHref']
    addDirectoryItem(plugin.handle,
                     plugin.url_for(page_api_url, url=content_url),
                     make_list_item(name, icon=fanart), True)
def index():
    refresh = arg_as_bool('refresh')
    clear_cache = arg_as_bool('clear-cache')
    if clear_cache:
        include_premium = adobe_activate_api.is_authenticated()
        channel_list = events.get_channel_list(include_premium)
        util.clear_cache(events.get_live_events_url(channel_list))

    current_time = time.strftime("%I:%M %p", time.localtime(time.time()))
    addDirectoryItem(plugin.handle, plugin.url_for(index, refresh=True),
                     ListItem(get_string(30850) % current_time), True)
    include_premium = adobe_activate_api.is_authenticated()
    channel_list = events.get_channel_list(include_premium)
    espn_url = events.get_live_events_url(channel_list)
    legacy.index_legacy_live_events(espn_url)
    if get_setting_as_bool('ShowAndroidTVMenu'):
        url = base64.b64decode(
            'aHR0cHM6Ly93YXRjaC5wcm9kdWN0LmFwaS5lc3BuLmNvbS9hcGkvcHJvZHVjdC92MS9hbmRyb2lkL3R2L2hvbWU='
        )
        addDirectoryItem(plugin.handle, plugin.url_for(page_api_url, url=url),
                         ListItem(get_string(30780)), True)
    if get_setting_as_bool('ShowAppleTVMenu'):
        addDirectoryItem(plugin.handle,
                         plugin.url_for(appletv.appletv_root_menu),
                         ListItem(get_string(30730)), True)
    if get_setting_as_bool('ShowLegacyMenu'):
        addDirectoryItem(plugin.handle, plugin.url_for(legacy_root_menu),
                         ListItem(get_string(30740)), True)
    if get_setting_as_bool('ShowRokuMenu'):
        addDirectoryItem(plugin.handle, plugin.url_for(roku.roku_root_menu),
                         ListItem(get_string(30760)), True)
    if get_setting_as_bool('ShowTVOSMenu'):
        addDirectoryItem(plugin.handle, plugin.url_for(tvos.tvos_root_menu),
                         ListItem(get_string(30750)), True)
    endOfDirectory(plugin.handle, updateListing=refresh, cacheToDisc=False)
Exemple #8
0
def roku_root_menu():
    # Roku config
    url = 'http://assets.espn.go.com/prod/assets/watchespn/roku/config.json'
    json_data = util.get_url_as_json_cache(get_url(url))
    for group in json_data['config']['featured']['groups']:
        if group['visibility'] == 'not authenticated':
            # This represents the duplicate Browse by Sport
            continue
        extra = ''
        if group['visibility'] == 'authenticated':
            if not adobe_activate_api.is_authenticated():
                extra = '*'
        if len(group['contents']) > 1:
            extra += group['name'] + ' - '
        for content in group['contents']:
            addDirectoryItem(
                plugin.handle,
                plugin.url_for(roku_url_mode, url=content['href']),
                ListItem(extra + content['name']), True)
    endOfDirectory(plugin.handle)
def index_v3_vod(content):
    plot = content.get('description', '')

    event_id = content['eventId'] if 'eventId' in content else content['id']

    more_than_one_stream = len(content['streams']) > 1
    for stream in content['streams']:
        duration = parse_duration(stream['duration'])
        duration_seconds = duration.tm_hour * 3600 + duration.tm_min * 60 + duration.tm_sec

        name = content['name']
        if more_than_one_stream:
            name = name + ' - ' + stream['name']

        ename, length = get_item_listing_text(name, None, duration_seconds,
                                              None, '', 'blackoutText'
                                              in content, [])

        source_name = util.get_nested_value(content,
                                            ['stream', 0, 'source', 'name'])

        fanart = util.get_nested_value(content, ['imageHref'])

        info_labels = {
            'title': ename,
            'duration': length,
            'studio': source_name,
            'plot': plot
        }

        addDirectoryItem(
            plugin.handle,
            plugin.url_for(play_vod,
                           event_id=event_id,
                           url=stream['links']['play']),
            make_list_item(ename, info_labels=info_labels, icon=fanart))
Exemple #10
0
def legacy_root_menu():
    include_premium = adobe_activate_api.is_authenticated()
    channel_list = events.get_channel_list(include_premium)
    curdate = datetime.utcnow()
    upcoming = get_setting_as_int('upcoming') + 1
    days = (curdate + timedelta(days=upcoming)).strftime("%Y%m%d")
    # Live
    addDirectoryItem(
        plugin.handle,
        plugin.url_for(live_events_mode,
                       espn_url=events.get_live_events_url(channel_list)),
        make_list_item(get_string(30029)), True)
    # Upcoming
    espn_url = events.get_upcoming_events_url(channel_list) + '&endDate=' + days \
        + '&startDate=' + curdate.strftime("%Y%m%d")
    addDirectoryItem(plugin.handle,
                     plugin.url_for(list_sports, espn_url=espn_url),
                     make_list_item(get_string(30030)), True)
    enddate = '&endDate=' + (curdate + timedelta(days=1)).strftime("%Y%m%d")
    replays1 = [5, 10, 15, 20, 25]
    replays1 = replays1[get_setting_as_int('replays1')]
    start1 = (curdate - timedelta(days=replays1)).strftime("%Y%m%d")
    replays2 = [10, 20, 30, 40, 50]
    replays2 = replays2[get_setting_as_int('replays2')]
    start2 = (curdate - timedelta(days=replays2)).strftime("%Y%m%d")
    replays3 = [30, 60, 90, 120]
    replays3 = replays3[get_setting_as_int('replays3')]
    start3 = (curdate - timedelta(days=replays3)).strftime("%Y%m%d")
    replays4 = [60, 90, 120, 240]
    replays4 = replays4[get_setting_as_int('replays4')]
    start4 = (curdate - timedelta(days=replays4)).strftime("%Y%m%d")
    start_all = (curdate - timedelta(days=365)).strftime("%Y%m%d")
    addDirectoryItem(
        plugin.handle,
        plugin.url_for(list_sports,
                       espn_url=events.get_replay_events_url(channel_list) +
                       enddate + '&startDate=' + start1),
        make_list_item(get_string(30031) % replays1), True)
    addDirectoryItem(
        plugin.handle,
        plugin.url_for(list_sports,
                       espn_url=events.get_replay_events_url(channel_list) +
                       enddate + '&startDate=' + start2),
        make_list_item(get_string(30031) % replays2), True)
    addDirectoryItem(
        plugin.handle,
        plugin.url_for(list_sports,
                       espn_url=events.get_replay_events_url(channel_list) +
                       enddate + '&startDate=' + start3),
        make_list_item(get_string(30031) % replays3), True)
    addDirectoryItem(
        plugin.handle,
        plugin.url_for(list_sports,
                       espn_url=events.get_replay_events_url(channel_list) +
                       '&endDate=' + start3 + '&startDate=' + start4),
        make_list_item(get_string(30033) % (replays3, replays4)), True)
    addDirectoryItem(
        plugin.handle,
        plugin.url_for(list_sports,
                       espn_url=events.get_replay_events_url(channel_list) +
                       enddate + '&startDate=' + start_all),
        make_list_item(get_string(30032)), True)
    xbmcplugin.endOfDirectory(plugin.handle)
Exemple #11
0
def index_legacy_live_events(espn_url, sport=None, network_id=None):
    chosen_sport = sport
    chosen_network = network_id
    live = 'action=live' in espn_url
    upcoming = 'action=upcoming' in espn_url
    replay = 'action=replay' in espn_url
    if live:
        data = events.get_events(espn_url)
    else:
        data = util.get_url_as_xml_cache(
            espn_url, encoding='ISO-8859-1').findall(".//event")
    num_espn3 = 0
    num_secplus = 0
    num_accextra = 0
    num_events = 0
    for event in data:
        sport = event.find('sportDisplayValue').text.encode('utf-8')
        if chosen_sport != sport and chosen_sport is not None:
            continue
        networkid = event.find('networkId').text
        if chosen_network != networkid and chosen_network is not None:
            continue
        if networkid == ESPN3_ID and chosen_network is None and live:
            num_espn3 += 1
        elif networkid == SECPLUS_ID and chosen_network is None and live:
            num_secplus += 1
        elif networkid == ACC_EXTRA_ID and chosen_network is None and live:
            num_accextra += 1
        else:
            num_events += 1
            _index_event(event, live, upcoming, replay, chosen_sport)
    # Don't show ESPN3 folder if there are no premium events
    if num_events == 0:
        for event in data:
            sport = event.find('sportDisplayValue').text.encode('utf-8')
            if chosen_sport != sport and chosen_sport is not None:
                continue
            _index_event(event, live, upcoming, replay, chosen_sport)
    # Dir for ESPN3/SECPlus/ACC Extra
    elif chosen_network is None:
        if num_espn3 > 0 and get_setting_as_bool('ShowEspn3'):
            translation_number = 30191 if num_espn3 == 1 else 30190
            name = (get_string(translation_number) % num_espn3)
            addDirectoryItem(
                plugin.handle,
                plugin.url_for(live_network_events_mode,
                               espn_url=espn_url,
                               network_id=ESPN3_ID), make_list_item(name),
                True)
        if num_secplus > 0 and get_setting_as_bool('ShowSecPlus'):
            translation_number = 30201 if num_secplus == 1 else 30200
            name = (get_string(translation_number) % num_secplus)
            addDirectoryItem(
                plugin.handle,
                plugin.url_for(live_network_events_mode,
                               espn_url=espn_url,
                               network_id=SECPLUS_ID), make_list_item(name),
                True)
        if num_accextra > 0 and get_setting_as_bool('ShowAccExtra'):
            translation_number = 30203 if num_accextra == 1 else 30202
            name = (get_string(translation_number) % num_accextra)
            addDirectoryItem(
                plugin.handle,
                plugin.url_for(live_network_events_mode,
                               espn_url=espn_url,
                               network_id=ACC_EXTRA_ID), make_list_item(name),
                True)
Exemple #12
0
def index_item(args):
    if args['type'] == 'over':
        return
    sport = args['sport']
    ename = args['eventName']
    sport2 = args['subcategory'] if 'subcategory' in args else sport
    if sport != sport2 and len(sport2) > 0:
        sport += ' (' + sport2 + ')'
    starttime = args['starttime'] if 'starttime' in args else None
    length = int(args['duration'])

    etime = time.time()
    if starttime is not None:
        now = time.time()
        etime = time.strftime("%I:%M %p", starttime)
        if 'replay' in args['type']:
            etime_local = starttime
            if etime_local.tm_hour == 0 and etime_local.tm_min == 0:
                etime = time.strftime("%m/%d/%Y", starttime)
            else:
                etime = time.strftime("%m/%d %I:%M %p", starttime)
            ename = etime + ' - ' + ename
        elif args['type'] == 'live':
            starttime_time = time.mktime(starttime)
            length -= (time.time() - starttime_time)
            ename += ' - ' + etime
        else:
            now_time = time.localtime(now)
            if now_time.tm_year == starttime.tm_year and \
                    now_time.tm_mon == starttime.tm_mon and \
                    now_time.tm_mday == starttime.tm_mday:
                etime = time.strftime("%I:%M %p", starttime)
            else:
                etime = time.strftime("%m/%d %I:%M %p", starttime)
            ename = etime + ' - ' + ename
        aired = time.strftime("%Y-%m-%d", starttime)
    else:
        aired = 0

    network_id = args['networkId'] if 'networkId' in args else ''
    if 'networkName' in args:
        network = args['networkName']
    else:
        network = network_id
    logging.debug('network_id ' + network_id)
    if network_id in NETWORK_ID_TO_NETWORK_NAME:
        network = get_string(NETWORK_ID_TO_NETWORK_NAME[network_id])
    blackout = args['blackout'] if 'blackout' in args else False
    blackout_text = ''
    if blackout:
        blackout_text = get_string(30580)
    if len(blackout_text) > 0:
        ename = blackout_text + ' ' + ename
    if len(network) > 0:
        if get_setting_as_bool('NoColors'):
            ename = network + ' ' + ename
        else:
            ename = '[B]%s[/B] ' % (network) + ename

    description = args['description']
    auth_types = get_auth_types_from_network(network_id)
    requires_auth = check_auth_types(auth_types)
    if requires_auth and not adobe_activate_api.is_authenticated():
        ename = '*' + ename

    logging.debug('Duration %s' % length)

    mpaa = args['parentalRating'] if 'parentRating' in args else 'U'
    info_labels = {
        'title': ename,
        'genre': sport,
        'duration': length,
        'studio': network,
        'mpaa': mpaa,
        'plot': description,
        'aired': aired,
        'premiered': aired
    }

    fanart = args['imageHref']

    if args['type'] == 'upcoming':
        addDirectoryItem(
            plugin.handle,
            plugin.url_for(upcoming_event,
                           event_id=args['eventId'],
                           starttime=etime,
                           event_name=quote_plus(ename.encode('utf-8'))),
            make_list_item(ename, icon=fanart, info_labels=info_labels))
    else:
        adobe_rss = args['adobeRSS'] if 'adobeRSS' in args else None
        guid = args['guid'] if 'guid' in args else None
        if adobe_rss is None and guid is None:
            addDirectoryItem(
                plugin.handle,
                plugin.url_for(play_item,
                               url=args['sessionUrl'],
                               event_id=args['eventId']),
                make_list_item(ename, icon=fanart, info_labels=info_labels))
        else:
            if 'adobeRSS' in args:
                adobe_rss = args['adobeRSS']
            else:
                adobe_rss = adobe_activate_api.get_resource(
                    args['channelResourceId'], args['eventName'], args['guid'],
                    mpaa)

            if include_item(network_id):
                logging.debug('Adding %s with handle %d and id %s' %
                              (ename, plugin.handle, args['eventId']))
                logging.debug(adobe_rss)
                addDirectoryItem(
                    plugin.handle,
                    plugin.url_for(play_tv,
                                   event_id=args['eventId'],
                                   session_url=args['sessionUrl'],
                                   network_name=args['networkId'],
                                   resource=quote_plus(
                                       adobe_rss.encode('utf-8'))),
                    make_list_item(ename, icon=fanart,
                                   info_labels=info_labels))
            else:
                logging.debug('Skipping %s' % args['networkId'])
Exemple #13
0
def roku_url_mode():
    url = arg_as_string('url')
    category_id = arg_as_string(ID)
    json_data = util.get_url_as_json_cache(get_url(url))
    if 'listings' in json_data:
        json_data['listings'].sort(key=functools.cmp_to_key(compare_roku))
        for listing in json_data['listings']:
            index_listing(listing)
        setContent(plugin.handle, 'episodes')
    if 'videos' in json_data:
        for video in json_data['videos']:
            index_video(video)
        setContent(plugin.handle, 'episodes')
    if 'categories' in json_data:
        for category in json_data['categories']:
            if category_id is None or category_id == '':
                if 'api' in category[
                        'links'] and 'subcategories' not in category:
                    addDirectoryItem(
                        plugin.handle,
                        plugin.url_for(
                            roku_url_mode,
                            url=category['links']['api']['video']['href']),
                        make_list_item(category['name'],
                                       get_thumbnail(category)), True)
                elif 'subcategories' in category:
                    # Collapse sub categories
                    for subcategory in category['subcategories']:
                        if 'api' in subcategory['links']:
                            addDirectoryItem(
                                plugin.handle,
                                plugin.url_for(roku_url_mode,
                                               url=subcategory['links']['api']
                                               ['video']['href']),
                                make_list_item(
                                    category['name'] +
                                    ' - ' + subcategory['name'],
                                    get_thumbnail(category)), True)
            elif category_id == str(category['id']):
                if 'api' in category['links']:
                    addDirectoryItem(
                        plugin.handle,
                        plugin.url_for(
                            roku_url_mode,
                            url=category['links']['api']['video']['href']),
                        make_list_item(category['name'] + ' - Clips',
                                       get_thumbnail(category)), True)
                if 'subcategories' in category:
                    for subcategory in category['subcategories']:
                        if 'api' in subcategory['links']:
                            addDirectoryItem(
                                plugin.handle,
                                plugin.url_for(roku_url_mode,
                                               url=subcategory['links']['api']
                                               ['video']['href']),
                                make_list_item(subcategory['name'],
                                               get_thumbnail(category)), True)
    if 'clients' in json_data:
        for client in json_data['clients']:
            for channel in client['channels']:
                addDirectoryItem(
                    plugin.handle,
                    plugin.url_for(
                        roku_url_mode,
                        url=channel['links']['api']['listings']['href']),
                    make_list_item(channel['name'], get_thumbnail(channel)),
                    True)
    endOfDirectory(plugin.handle)
def index_v3_content(content):
    logging.debug('Indexing %s' % content)
    content_type = content['type']
    if content_type == 'show' or content_type == 'film' or content_type == 'product':
        index_v3_show(content)
        return
    if content_type == 'vod':
        index_v3_vod(content)
        return

    status = content['status']

    subtitle = content.get('subtitle', '')
    plot = subtitle
    if 'event' in content:
        event = content['event']
        if event['type'] == 'tvt':
            plot = '%s\n%s vs. %s\n%s - %s\n%s%s' % \
                   (subtitle,
                    get_team_name(event, 'One'),
                    get_team_name(event, 'Two'),
                    event['teamOneScore'], event['teamTwoScore'],
                    get_possesion_text(event),
                    event['statusTextOne'])
    if 'plot' in content:
        plot = content['plot']

    starttime = get_time(content)
    if 'date' in content and 'time' in content:
        plot = content['date'] + ' ' + content['time'] + '\n' + plot

    event_id = content['eventId'] if 'eventId' in content else content['id']

    more_than_one_stream = len(content['streams']) > 1
    for stream in content['streams']:
        if 'duration' in stream:
            duration = parse_duration(stream['duration'])
            duration_seconds = duration.tm_hour * 3600 + duration.tm_min * 60 + duration.tm_sec
        else:
            duration_seconds = 0

        name = content['name']
        if more_than_one_stream:
            name = name + ' - ' + stream['name']

        entitlements = espnplus.get_entitlements()
        packages = util.get_nested_value(stream, ['packages'], [])
        has_entitlement = is_entitled(packages, entitlements)
        ename, length = get_item_listing_text(
            name,
            starttime,
            duration_seconds,
            content['status'],
            stream['source']['name'],
            'blackoutText' in content,
            stream['authTypes'],
            requires_package=not has_entitlement)

        source_name = util.get_nested_value(stream, ['source', 'name'], '')

        fanart = util.get_nested_value(content, ['imageHref'])

        info_labels = {
            'title': ename,
            'genre': subtitle,
            'duration': length,
            'studio': source_name,
            'plot': plot
        }

        logging.debug('Checking to include %s' % source_name.lower())
        if include_item(source_name.lower()):
            if status == 'upcoming':
                starttime_text = time.strftime("%m/%d/%Y %I:%M %p", starttime)
                addDirectoryItem(
                    plugin.handle,
                    plugin.url_for(upcoming_event,
                                   event_id=event_id,
                                   event_name=quote_plus(name.encode('utf-8')),
                                   starttime=starttime_text,
                                   packages='|'.join(packages)),
                    make_list_item(ename, info_labels=info_labels))
            else:
                addDirectoryItem(
                    plugin.handle,
                    plugin.url_for(play_event,
                                   event_id=event_id,
                                   event_url=stream['links']['play'],
                                   auth_types='|'.join(stream['authTypes']),
                                   packages='|'.join(packages)),
                    make_list_item(ename, info_labels=info_labels,
                                   icon=fanart))
        else:
            logger.debug('Skipping item because of settings')
def index_bucket_content(url, bucket, channel_filter):
    if 'contents' in bucket:
        bucket['contents'].sort(key=functools.cmp_to_key(compare_contents))
        grouped_events = dict()
        source_id_data = dict()
        content_indexed = 0
        for content in bucket['contents']:
            content_type = content['type']
            if content_type in [
                    'network', 'subcategory', 'category', 'program'
            ]:
                content_url = content['links']['self']
                if 'imageHref' in content:
                    fanart = content['imageHref']
                else:
                    fanart = None
                listitem = ListItem(content['name'])
                listitem.setArt({'icon': fanart})
                addDirectoryItem(plugin.handle,
                                 plugin.url_for(page_api_url, url=content_url),
                                 listitem, True)
            else:
                setContent(plugin.handle, 'episodes')
                source_id = util.get_nested_value(
                    content, ['streams', 0, 'source', 'id'])
                source_name = util.get_nested_value(
                    content, ['streams', 0, 'source', 'name'])
                channel_id = make_channel_id(source_id, source_name)
                if channel_filter is None:
                    source_type = util.get_nested_value(
                        content, ['streams', 0, 'source', 'type'])
                    if source_type == 'online':
                        if channel_id not in grouped_events:
                            grouped_events[channel_id] = []
                        grouped_events[channel_id].append(content)
                        source_id_data[channel_id] = {
                            'name': source_name,
                            'id': source_id
                        }
                    else:
                        index_content(content)
                        content_indexed = content_indexed + 1
                elif channel_filter == channel_id:
                    index_content(content)
                    content_indexed = content_indexed + 1

        # Handle grouped contents
        group_source_ids = list(grouped_events.keys())
        group_source_ids.sort(key=functools.cmp_to_key(compare_network_ids))
        for group_source_id in group_source_ids:
            contents = grouped_events[group_source_id]
            source_data = source_id_data[group_source_id]
            # Index the content directly if he haven't indexed a lot of things
            if content_indexed <= 3:
                for content in contents:
                    index_content(content)
            else:
                name = source_data['name']
                channel_id = source_data['id']
                if len(name) == 0 and channel_id == 'ESPN_PPV':
                    name = 'ESPN+ PPV'
                elif len(name) == 0:
                    name = channel_id
                addDirectoryItem(
                    plugin.handle,
                    plugin.url_for(page_api_channel,
                                   channel_id=group_source_id,
                                   url=url), ListItem(name), True)