def index():
    items = [{
        'label': sc.long_name,
        'path': plugin.url_for(
            'get_season_menu', siteid=index,
            cls=sc.__name__),
        'thumbnail': util.get_image_path(sc.local_thumb),
        'icon': util.get_image_path(sc.local_thumb),
        } for index, sc in enumerate(BaseForum.__subclasses__())]

    by_label = itemgetter('label')
    items = sorted(items, key=by_label)

    # insert bookmarks at top
    items.insert(0, {
        'label': '[B]{txt}[/B]'.format(txt=_('bookmarks')),
        'path': plugin.url_for('show_bookmarks'),
        'thumbnail': util.get_image_path('bookmark.png')})

    # add url resolver settings at bottom
    thumb = util.get_image_path('settings.png')
    items.append({
        'label': '[COLOR white]{txt}[/COLOR]'.format(
            txt=_('url_resolver_settings')),
        'path': plugin.url_for('get_urlresolver_settings'),
        'thumbnail': thumb,
        'icon': thumb
        })
    return items
Beispiel #2
0
def browse_frame(siteid, cls, frameid):
    siteid = int(siteid)
    url = plugin.request.args['url'][0]
    api = BaseForum.__subclasses__()[siteid]()

    plugin.log.debug('browse frame: {frame}'.format(frame=url))

    # Some forum frames contain shows
    # while others contain episodes
    contents, contype = get_cached(api.browse_frame, frameid, url)
    if contype and contype == s.ThreadType().Episode:
        items = [{
            'label': item['label'],
            'path': plugin.url_for(
                'get_episode_data', siteid=siteid, cls=cls, frameid=frameid,
                epid=item.get('pk', '0'), url=item['url'])
        } for item in contents]
    else:
        items = [{
            'label': item['label'],
            'path': plugin.url_for(
                'browse_shows', siteid=siteid, cls=cls, frameid=frameid,
                showid=item.get('pk', '0'), showpage=1, url=item['url'])
        } for item in contents]

    return __add_listitem(groupname=api.short_name, items=items)
def play_video(siteid, cls, epid, partnum):
    siteid = int(siteid)
    api = BaseForum.__subclasses__()[siteid]()

    part_media = plugin.request.args['media'][0]
    media = []

    import urlresolver
    for host, vid in sorted(part_media, key=lambda x: x[0].server):
        r = urlresolver.HostedMediaFile(host=host.server, media_id=vid)
        if r:
            media.append(r)

    source = urlresolver.choose_source(media)
    plugin.log.debug('>>> Source selected')
    plugin.log.debug(source)

    if source:
        url = source.resolve()
        plugin.log.debug('play video: {url}'.format(url=url))

        plugin.set_resolved_url(url)

    else:
        msg = [_('cannot_play'), _('choose_source')]
        plugin.log.error(msg[0])
        dialog = xbmcgui.Dialog()
        dialog.ok(api.long_name, *msg)
def browse_channels(siteid, cls, channelid):
    siteid = int(siteid)
    api = BaseForum.__subclasses__()[siteid]()

    plugin.log.debug('browse channel: {channel}'.format(channel=channelid))

    channels, shows = get_cached(api.get_show_menu, channelid)

    showitems = [{
        'label':
        item['label'],
        'path':
        plugin.url_for('browse_shows',
                       siteid=siteid,
                       cls=cls,
                       showid=item['pk'],
                       showpage=1,
                       url=item['url'])
    } for item in shows]

    channelitems = [{
        'label':
        '[B]{item}[/B]'.format(item=item['label']),
        'path':
        plugin.url_for('browse_channels',
                       siteid=siteid,
                       cls=cls,
                       channelid=item['pk'],
                       url=item['url'])
    } for item in channels]

    by_label = itemgetter('label')
    items = showitems + sorted(channelitems, key=by_label)
    return __add_listitem(groupname=api.short_name, items=items)
Beispiel #5
0
def browse_channels(siteid, cls, channelid):
    siteid = int(siteid)
    api = BaseForum.__subclasses__()[siteid]()

    plugin.log.debug('browse channel: {channel}'.format(channel=channelid))

    channels, shows = get_cached(api.get_show_menu, channelid)

    showitems = [{
        'label': item['label'],
        'path': plugin.url_for(
            'browse_shows', siteid=siteid, cls=cls,
            showid=item['pk'], showpage=1, url=item['url'])
    } for item in shows]

    channelitems = [{
        'label': '[B]{item}[/B]'.format(item=item['label']),
        'path': plugin.url_for(
            'browse_channels', siteid=siteid, cls=cls,
            channelid=item['pk'], url=item['url'])
    } for item in channels]

    by_label = itemgetter('label')
    items = showitems + sorted(channelitems, key=by_label)
    return __add_listitem(groupname=api.short_name, items=items)
def get_show_menu(siteid, cls, seasonid):
    siteid = int(siteid)
    base_url = plugin.request.args['url'][0]
    api = BaseForum.__subclasses__()[siteid]()
    lang = LANG.get(api.short_name, '')

    plugin.log.debug('browse season: {season}'.format(season=seasonid))

    items = []

    data = get_cached(api.get_show_menu, lang, base_url)

    if data:
        items = [{
            'label': item['label'],
            'path': plugin.url_for(
                'get_episode_menu', siteid=siteid, cls=cls,
                seasonid=seasonid, episodeid=item['pk'],
                base_url=base_url, url=item['url'])
        } for item in data]

        grouping = api.short_name + ' - s' + seasonid + ' '
        return __add_listitem(groupname=grouping, items=items)
    else:
        msg = '[B][COLOR red]{txt}[/COLOR][/B]'.format(
            txt=_('no_episodes'))
        plugin.log.error(msg)
        dialog = xbmcgui.Dialog()
        dialog.ok(api.long_name, msg)
Beispiel #7
0
def play_video(siteid, cls, epid, partnum):
    siteid = int(siteid)
    api = BaseForum.__subclasses__()[siteid]()

    part_media = plugin.request.args['media'][0]
    media = []

    import urlresolver
    for host, vid in sorted(part_media, key=lambda x: x[0].server):
        r = urlresolver.HostedMediaFile(
            host=host.server, media_id=vid)
        if r:
            media.append(r)

    source = urlresolver.choose_source(media)
    plugin.log.debug('>>> Source selected')
    plugin.log.debug(source)

    if source:
        url = source.resolve()

        if not __is_resolved(url):
            msg = str(url.msg)
            raise Exception(msg)

        else:
            plugin.log.debug('play video: {url}'.format(url=url))
            plugin.set_resolved_url(url)        
        
    else:
        msg = [_('cannot_play'), _('choose_source')]
        plugin.log.error(msg[0])
        dialog = xbmcgui.Dialog()
        dialog.ok(api.long_name, *msg)
def play_video_continuous(siteid, cls, epid):
    siteid = int(siteid)
    api = BaseForum.__subclasses__()[siteid]()

    temp = plugin.get_storage(temp_storage)
    data = temp['items']

    part_media = data[0]['media']

    media = []

    import urlresolver
    for host, vid in sorted(part_media, key=lambda x: x[0].server):
        r = urlresolver.HostedMediaFile(host=host.server, media_id=vid)
        if r:
            media.append(r)

    source = urlresolver.choose_source(media)
    plugin.log.debug('>>> Source selected')
    plugin.log.debug(source)

    if source:
        selected_host = source.get_host()
        plugin.log.debug('play from host {host}'.format(host=selected_host))

        items = []

        for part in data:
            medialist = part['media']
            stream_url, thumb = __resolve_part(medialist, selected_host)

            items.append({
                'label':
                'Continuous Play: {part}'.format(part=part['label']),
                'path':
                stream_url,
                'thumbnail':
                thumb,
                'icon':
                thumb,
            })

        xbmc.PlayList(xbmc.PLAYLIST_VIDEO).clear()
        plugin.add_to_playlist(items)

        # Setting resolved url for first item
        # otherwise playlist seems to skip it
        plugin.set_resolved_url(items[0])

    else:
        msg = [_('cannot_play'), _('choose_source')]
        plugin.log.error(msg[0])
        dialog = xbmcgui.Dialog()
        dialog.ok(api.long_name, *msg)
Beispiel #9
0
def get_category_menu(siteid, cls):
    siteid = int(siteid)
    api = BaseForum.__subclasses__()[siteid]()

    plugin.log.debug('browse site: {site}'.format(site=cls))

    # check if site is available
    if api.base_url:
        available = util.is_site_available(api.base_url)

        if available:
            frameitems = []
            categoryitems = []

            # get frames
            f = api.get_frame_menu()
            if f:
                frameitems = [{
                    'label': item['label'],
                    'path': plugin.url_for(
                        'browse_frame', siteid=siteid, cls=cls,
                        frameid=index, url=item['url'])
                } for index, item in enumerate(f)]

            # get categories
            c = api.get_category_menu()
            if c:
                categoryitems = [{
                    'label': '[B]{item}[/B]'.format(item=item['label']),
                    'path': plugin.url_for(
                        'browse_category', siteid=siteid, cls=cls,
                        categoryid=item['categoryid'])
                } for item in c]

            by_label = itemgetter('label')
            items = frameitems + sorted(categoryitems, key=by_label)
            return items

        else:
            msg = [
                '[B][COLOR red]{txt}[/COLOR][/B]'.format(
                    txt=_('site_unavailable')),
                '{site} {txt}'.format(
                    site=api.long_name, txt=_('is_unavailable')),
                _('try_again_later')]
            plugin.log.error(msg[1])

            dialog = xbmcgui.Dialog()
            dialog.ok(api.long_name, *msg)
    else:
        msg = 'Base url not implemented'
        plugin.log.error(msg)
        raise Exception(msg)
def get_episode_data(siteid, cls, epid):
    siteid = int(siteid)
    url = plugin.request.args['url'][0]
    api = BaseForum.__subclasses__()[siteid]()

    plugin.log.debug('browse episode: {ep}'.format(ep=url))

    data = api.get_episode_data(url)
    if data:
        items = [{
            'label':
            item['label'],
            'path':
            plugin.url_for('play_video',
                           siteid=siteid,
                           cls=cls,
                           epid=epid,
                           partnum=item['partnum'],
                           media=item['media']),
            'is_playable':
            True
        } for item in data]

        # Add continuous play to top
        # if Single Link (Part 0) does not exist
        # and more than 1 parts
        if (data[0]['partnum'] != 0 and len(data) > 1):

            # save post data to temp
            temp = plugin.get_storage(temp_storage)
            temp.clear()
            temp['items'] = data

            items.insert(
                0, {
                    'label':
                    'Continuous Play',
                    'path':
                    plugin.url_for('play_video_continuous',
                                   siteid=siteid,
                                   cls=cls,
                                   epid=epid),
                    'is_playable':
                    True
                })

        return items

    else:
        msg = '[B][COLOR red]{txt}[/COLOR][/B]'.format(txt=_('no_valid_links'))
        plugin.log.error(msg)
        dialog = xbmcgui.Dialog()
        dialog.ok(api.long_name, msg)
def get_episode_menu(siteid, cls, seasonid, episodeid):
    siteid = int(siteid)
    base_url = plugin.request.args['base_url'][0]
    url = plugin.request.args['url'][0]
    api = BaseForum.__subclasses__()[siteid]()
    # lang = LANG.get(api.short_name, '')

    plugin.log.debug('browse episode: {episode}'.format(episode=url))

    items = []

    data = api.get_episode_menu(base_url, url)

    if data:
        items = [{
            'label': item['label'],
            'thumbnail': item['thumb'],
            'icon': item['thumb'],
            'info': {
                'plot': item['plot']
            },
            'path': plugin.url_for(
                'play_video', siteid=siteid, cls=cls,
                seasonid=seasonid, episodeid=episodeid,
                videoid=item.get('pk', 0), url=item['url']),
            'is_playable': True
        } for item in data]

        # Add continuous play to top
        # if more than 1 item
        if len(items) > 1:
            # save post data to temp
            temp = plugin.get_storage(temp_storage)
            temp.clear()
            temp['items'] = data

            items.insert(0, {
                'label': '[B][COLOR white]Continuous Play[/COLOR][/B]',
                'path': plugin.url_for(
                    'play_video_continuous', siteid=siteid, cls=cls,
                    seasonid=seasonid, episodeid=episodeid,
                    videoid=item.get('pk', 0), url=item['url']),
                'is_playable': True
            })

        return items
    else:
        msg = '[B][COLOR red]{txt}[/COLOR][/B]'.format(
            txt=_('no_valid_links'))
        plugin.log.error(msg)
        dialog = xbmcgui.Dialog()
        dialog.ok(api.long_name, msg)
Beispiel #12
0
def play_video_continuous(siteid, cls, epid):
    siteid = int(siteid)
    api = BaseForum.__subclasses__()[siteid]()

    temp = plugin.get_storage(temp_storage)
    data = temp['items']

    part_media = data[0]['media']

    media = []

    import urlresolver
    for host, vid in sorted(part_media, key=lambda x: x[0].server):
        r = urlresolver.HostedMediaFile(
            host=host.server, media_id=vid)
        if r:
            media.append(r)

    source = urlresolver.choose_source(media)
    plugin.log.debug('>>> Source selected')
    plugin.log.debug(source)

    if source:
        selected_host = source.get_host()
        plugin.log.debug('play from host {host}'.format(host=selected_host))

        items = []

        for part in data:
            medialist = part['media']
            stream_url, thumb = __resolve_part(medialist, selected_host)

            items.append({
                'label': 'Continuous Play: {part}'.format(part=part['label']),
                'path': stream_url,
                'thumbnail': thumb,
                'icon': thumb,
            })

        xbmc.PlayList(xbmc.PLAYLIST_VIDEO).clear()
        plugin.add_to_playlist(items)

        # Setting resolved url for first item
        # otherwise playlist seems to skip it
        plugin.set_resolved_url(items[0])

    else:
        msg = [_('cannot_play'), _('choose_source')]
        plugin.log.error(msg[0])
        dialog = xbmcgui.Dialog()
        dialog.ok(api.long_name, *msg)
def get_season_menu(siteid, cls):
    siteid = int(siteid)
    api = BaseForum.__subclasses__()[siteid]()
    lang = LANG.get(api.short_name, '')

    plugin.log.debug('browse site: {site}'.format(site=cls))

    # check if site is available
    if api.base_url:
        available = util.is_site_available(api.base_url)

        if available:
            items = []

            # siteid provides unique key for cache
            # as lang not always present
            data = get_cached(api.get_season_menu, siteid, lang)

            if data:
                items = [{
                    'label': item['label'].encode('utf-8'),
                    'path': plugin.url_for(
                        'get_show_menu', siteid=siteid, cls=cls,
                        seasonid=item['pk'], url=item['url'])
                } for item in data]

                return __add_listitem(groupname=api.short_name, items=items)

            else:
                msg = '[B][COLOR red]{txt}[/COLOR][/B]'.format(
                    txt=_('no_seasons'))
                plugin.log.error(msg)
                dialog = xbmcgui.Dialog()
                dialog.ok(api.long_name, msg)

        else:
            msg = [
                '[B][COLOR red]{txt}[/COLOR][/B]'.format(
                    txt=_('site_unavailable')),
                '{site} {txt}'.format(
                    site=api.long_name, txt=_('is_unavailable')),
                _('try_again_later')]
            plugin.log.error(msg[1])

            dialog = xbmcgui.Dialog()
            dialog.ok(api.long_name, *msg)
    else:
        msg = 'Base url not implemented'
        plugin.log.error(msg)
        raise Exception(msg)
Beispiel #14
0
def get_episode_data(siteid, cls, epid):
    siteid = int(siteid)
    url = plugin.request.args['url'][0]
    api = BaseForum.__subclasses__()[siteid]()

    plugin.log.debug('browse episode: {ep}'.format(ep=url))

    data = api.get_episode_data(url)
    if data:
        items = [{
            'label': item['label'],
            'path': plugin.url_for(
                'play_video', siteid=siteid, cls=cls,
                epid=epid, partnum=item['partnum'],
                media=item['media']),
            'is_playable': True
            } for item in data]

        # Add continuous play to top
        # if Single Link (Part 0) does not exist
        # and more than 1 parts
        if (data[0]['partnum'] != 0 and
                len(data) > 1):

            # save post data to temp
            temp = plugin.get_storage(temp_storage)
            temp.clear()
            temp['items'] = data

            items.insert(0, {
                'label': 'Continuous Play',
                'path': plugin.url_for(
                    'play_video_continuous', siteid=siteid, cls=cls,
                    epid=epid),
                'is_playable': True
            })

        return items

    else:
        msg = '[B][COLOR red]{txt}[/COLOR][/B]'.format(
            txt=_('no_valid_links'))
        plugin.log.error(msg)
        dialog = xbmcgui.Dialog()
        dialog.ok(api.long_name, msg)
def browse_shows(siteid, cls, showid, showpage=1):
    siteid = int(siteid)
    url = plugin.request.args['url'][0]
    api = BaseForum.__subclasses__()[siteid]()

    showpage = int(showpage)

    plugin.log.debug('browse show: {show}'.format(show=url))

    videos, next_url = get_cached(api.get_episode_menu, url, showpage)

    items = []

    if videos:
        items = [{
            'label':
            item['label'],
            'path':
            plugin.url_for('get_episode_data',
                           siteid=siteid,
                           cls=cls,
                           showid=showid,
                           epid=item.get('pk', 0),
                           url=item['url'])
        } for item in videos]

        if next_url:
            items.append({
                'label':
                'Next >>',
                'path':
                plugin.url_for('browse_shows',
                               siteid=siteid,
                               cls=cls,
                               showid=showid,
                               showpage=str(showpage + 1),
                               url=next_url)
            })

        return __add_listitem(groupname=api.short_name, items=items)
    else:
        msg = '[B][COLOR red]{txt}[/COLOR][/B]'.format(txt=_('no_episodes'))
        plugin.log.error(msg)
        dialog = xbmcgui.Dialog()
        dialog.ok(api.long_name, msg)
Beispiel #16
0
def browse_category(siteid, cls, categoryid):
    siteid = int(siteid)
    api = BaseForum.__subclasses__()[siteid]()

    plugin.log.debug('browse category: {category}'.format(category=categoryid))

    items = [{
        'label': item.label,
        'thumbnail': item.thumb,
        'icon': item.thumb,
        'path': plugin.url_for(
            'browse_channels', siteid=siteid, cls=cls,
            channelid=item.id)
    } for item in api.get_channel_menu(categoryid)]

    by_label = itemgetter('label')
    return __add_listitem(groupname=api.short_name,
                          items=sorted(items, key=by_label))
def play_video(siteid, cls, seasonid, episodeid, videoid):
    siteid = int(siteid)
    url = plugin.request.args['url'][0]
    api = BaseForum.__subclasses__()[siteid]()

    # print 'resolve video: {url}'.format(url=url)
    plugin.log.debug('resolve video: {url}'.format(url=url))
    media = __resolve_item(url, videoid)

    # print 'resolved to: {url}'.format(url=media)

    if media:
        plugin.set_resolved_url(media)
    else:
        msg = [_('cannot_play')]
        plugin.log.error(msg[0])
        dialog = xbmcgui.Dialog()
        dialog.ok(api.long_name, *msg)
def index():
    items = [{
        'label': '[B]{txt}[/B]'.format(txt=_('bookmarks')),
        'path': plugin.url_for('show_bookmarks'),
        'thumbnail': util.get_image_path('bookmark.png')
    }]

    items.extend([{
        'label':
        sc.long_name,
        'path':
        plugin.url_for('get_category_menu', siteid=index, cls=sc.__name__),
        'thumbnail':
        util.get_image_path(sc.local_thumb),
        'icon':
        util.get_image_path(sc.local_thumb),
    } for index, sc in enumerate(BaseForum.__subclasses__())])

    # live streams if xml url specified
    url = plugin.get_setting(livestream_xml_url, str)
    if url:
        thumb = util.get_image_path('thumb_live.jpg')
        items.append({
            'label': '[B]{txt}[/B]'.format(txt=_('live_streams')),
            'path': plugin.url_for('get_live_channels'),
            'thumbnail': thumb,
            'icon': thumb
        })

    thumb = util.get_image_path('settings.png')
    items.append({
        'label':
        '[COLOR white]{txt}[/COLOR]'.format(txt=_('url_resolver_settings')),
        'path':
        plugin.url_for('get_urlresolver_settings'),
        'thumbnail':
        thumb,
        'icon':
        thumb
    })
    return items
def browse_category(siteid, cls, categoryid):
    siteid = int(siteid)
    api = BaseForum.__subclasses__()[siteid]()

    plugin.log.debug('browse category: {category}'.format(category=categoryid))

    items = [{
        'label':
        item.label,
        'thumbnail':
        item.thumb,
        'icon':
        item.thumb,
        'path':
        plugin.url_for('browse_channels',
                       siteid=siteid,
                       cls=cls,
                       channelid=item.id)
    } for item in api.get_channel_menu(categoryid)]

    by_label = itemgetter('label')
    return __add_listitem(groupname=api.short_name,
                          items=sorted(items, key=by_label))
Beispiel #20
0
def browse_shows(siteid, cls, showid, showpage=1):
    siteid = int(siteid)
    url = plugin.request.args['url'][0]
    api = BaseForum.__subclasses__()[siteid]()

    showpage = int(showpage)

    plugin.log.debug('browse show: {show}'.format(show=url))

    videos, next_url = get_cached(api.get_episode_menu, url, showpage)

    items = []

    if videos:
        items = [{
            'label': item['label'],
            'path': plugin.url_for(
                'get_episode_data', siteid=siteid, cls=cls,
                showid=showid, epid=item.get('pk', 0), url=item['url'])
        } for item in videos]

        if next_url:
            items.append({
                'label': 'Next >>',
                'path': plugin.url_for(
                    'browse_shows', siteid=siteid,
                    cls=cls, showid=showid, showpage=str(showpage + 1),
                    url=next_url)
            })

        return __add_listitem(groupname=api.short_name, items=items)
    else:
        msg = '[B][COLOR red]{txt}[/COLOR][/B]'.format(
            txt=_('no_episodes'))
        plugin.log.error(msg)
        dialog = xbmcgui.Dialog()
        dialog.ok(api.long_name, msg)
def browse_frame(siteid, cls, frameid):
    siteid = int(siteid)
    url = plugin.request.args['url'][0]
    api = BaseForum.__subclasses__()[siteid]()

    plugin.log.debug('browse frame: {frame}'.format(frame=url))

    # Some forum frames contain shows
    # while others contain episodes
    contents, contype = get_cached(api.browse_frame, frameid, url)
    if contype and contype == s.ThreadType().Episode:
        items = [{
            'label':
            item['label'],
            'path':
            plugin.url_for('get_episode_data',
                           siteid=siteid,
                           cls=cls,
                           frameid=frameid,
                           epid=item.get('pk', '0'),
                           url=item['url'])
        } for item in contents]
    else:
        items = [{
            'label':
            item['label'],
            'path':
            plugin.url_for('browse_shows',
                           siteid=siteid,
                           cls=cls,
                           frameid=frameid,
                           showid=item.get('pk', '0'),
                           showpage=1,
                           url=item['url'])
        } for item in contents]

    return __add_listitem(groupname=api.short_name, items=items)
Beispiel #22
0
def index():
    items = [{
        'label': '[B]{txt}[/B]'.format(txt=_('bookmarks')),
        'path': plugin.url_for('show_bookmarks'),
        'thumbnail': util.get_image_path('bookmark.png')}]

    items.extend([{
        'label': sc.long_name,
        'path': plugin.url_for(
            'get_category_menu', siteid=index,
            cls=sc.__name__),
        'thumbnail': util.get_image_path(sc.local_thumb),
        'icon': util.get_image_path(sc.local_thumb),
        } for index, sc in enumerate(BaseForum.__subclasses__())])

    # live streams if xml url specified
    url = plugin.get_setting(livestream_xml_url, str)
    if url:
        thumb = util.get_image_path('thumb_live.jpg')
        items.append({
            'label': '[B]{txt}[/B]'.format(
                txt=_('live_streams')),
            'path': plugin.url_for('get_live_channels'),
            'thumbnail': thumb,
            'icon': thumb
        })

    thumb = util.get_image_path('settings.png')
    items.append({
        'label': '[COLOR white]{txt}[/COLOR]'.format(
            txt=_('url_resolver_settings')),
        'path': plugin.url_for('get_urlresolver_settings'),
        'thumbnail': thumb,
        'icon': thumb
        })
    return items
def get_category_menu(siteid, cls):
    siteid = int(siteid)
    api = BaseForum.__subclasses__()[siteid]()

    plugin.log.debug('browse site: {site}'.format(site=cls))

    # check if site is available
    if api.base_url:
        available = util.is_site_available(api.base_url)

        if available:
            frameitems = []
            categoryitems = []

            # get frames
            f = api.get_frame_menu()
            if f:
                frameitems = [{
                    'label':
                    item['label'],
                    'path':
                    plugin.url_for('browse_frame',
                                   siteid=siteid,
                                   cls=cls,
                                   frameid=index,
                                   url=item['url'])
                } for index, item in enumerate(f)]

            # get categories
            c = api.get_category_menu()
            if c:
                categoryitems = [{
                    'label':
                    '[B]{item}[/B]'.format(item=item['label']),
                    'path':
                    plugin.url_for('browse_category',
                                   siteid=siteid,
                                   cls=cls,
                                   categoryid=item['categoryid'])
                } for item in c]

            by_label = itemgetter('label')
            items = frameitems + sorted(categoryitems, key=by_label)
            return items

        else:
            msg = [
                '[B][COLOR red]{txt}[/COLOR][/B]'.format(
                    txt=_('site_unavailable')),
                '{site} {txt}'.format(site=api.long_name,
                                      txt=_('is_unavailable')),
                _('try_again_later')
            ]
            plugin.log.error(msg[1])

            dialog = xbmcgui.Dialog()
            dialog.ok(api.long_name, *msg)
    else:
        msg = 'Base url not implemented'
        plugin.log.error(msg)
        raise Exception(msg)