예제 #1
0
def play(params):
    try:
        import drmhelper
        if not drmhelper.check_inputstream(drm=False):
            return
    except ImportError:
        utils.log("Failed to import drmhelper")
        utils.dialog_message('DRM Helper is needed for inputstream.adaptive '
                             'playback. For more information, please visit: '
                             'http://aussieaddons.com/drm')
        return

    try:
        stream = comm.get_stream(params['video_id'])

        utils.log('Attempting to play: {0} {1}'.format(stream['name'],
                                                       stream['url']))
        item = xbmcgui.ListItem(label=stream['name'], path=stream['url'])
        item.setProperty('inputstreamaddon', 'inputstream.adaptive')
        item.setProperty('inputstream.adaptive.manifest_type', 'hls')
        item.setMimeType('application/vnd.apple.mpegurl')
        item.setContentLookup(False)
        xbmcplugin.setResolvedUrl(pluginhandle, True, listitem=item)
    except Exception:
        utils.handle_error('Unable to play video')
예제 #2
0
def router(paramstring):
    """
    Router function that calls other functions
    depending on the provided paramstring
    :param paramstring:
    """
    params = dict(parse_qsl(paramstring))
    utils.log('Running with params: {0}'.format(params))
    if params:
        if params['action'] == 'listcategories':
            if params['category'] == 'Live Matches':
                menu.list_matches(params, live=True)
            elif params['category'] == 'Settings':
                addon.openSettings()
            else:
                menu.list_videos(params)
        elif params['action'] in ['listvideos', 'listmatches']:
            play.play_video(params)
        elif params['action'] == 'clearticket':
            stream_auth.clear_ticket()
        elif params['action'] == 'open_ia_settings':
            try:
                import drmhelper
                if drmhelper.check_inputstream(drm=False):
                    ia = drmhelper.get_addon()
                    ia.openSettings()
                else:
                    utils.dialog_message(
                        "Can't open inputstream.adaptive settings")
            except Exception:
                utils.dialog_message(
                    "Can't open inputstream.adaptive settings")
    else:
        menu.list_categories()
def get_embed_token(pai, bearer, video_id):
    """
    send our user token to get our embed token, including api key
    """
    url = config.TELSTRA_AUTH_URL.format(code=video_id, pai=pai)
    sess.headers = {}
    sess.headers.update({'Authorization': 'Bearer {0}'.format(bearer)})
    try:
        req = sess.get(url)
        data = req.text
        json_data = json.loads(data)
        if json_data.get('ErrorCode') is not None:
            raise AussieAddonsException()
        embed_token = json_data.get('token')
    except requests.exceptions.HTTPError as e:
        utils.log('Error getting embed token. '
                  'Response: {0}'.format(e.response.text))
        cache.delete('SOCCERTICKET')
        if e.response.status_code == 401:
            raise AussieAddonsException('Login token has expired, '
                                        'please try again.')
        else:
            raise e

    return urllib.quote_plus(embed_token)
예제 #4
0
def get_media_auth_token(ticket, video_id):
    """
    send our user token to get our embed token, including api key
    """
    url = config.MEDIA_AUTH_URL.format(video_id=video_id)
    sess.headers = {}
    sess.headers.update({
        'X-YinzCam-Ticket': ticket,
        'Accept': 'application/json'
    })
    try:
        req = sess.get(url)
        data = req.text
        json_data = json.loads(data)
        if json_data.get('Fault'):
            raise AussieAddonsException(
                json_data.get('fault').get('faultstring'))
        media_auth_token = json_data.get('VideoToken')
    except requests.exceptions.HTTPError as e:
        utils.log('Error getting embed token. '
                  'Response: {0}'.format(e.response.text))
        cache.delete('NETBALLTICKET')
        if e.response.status_code == 401:
            raise AussieAddonsException('Login token has expired, '
                                        'please try again.')
        else:
            raise e
    return media_auth_token
예제 #5
0
def get_embed_token(user_token, video_id):
    """
    send our user token to get our embed token, including api key
    """
    url = config.EMBED_TOKEN_URL.format(video_id)
    sess.headers.update({
        'X-YinzCam-Ticket': user_token,
        'Accept': 'application/json'
    })
    try:
        req = sess.get(url)
        data = req.text
        json_data = json.loads(data)
        if json_data.get('ErrorCode') is not None:
            raise AussieAddonsException()
        video_token = json_data.get('VideoToken')
    except requests.exceptions.HTTPError as e:
        utils.log('Error getting embed token. '
                  'Response: {0}'.format(e.response.text))
        cache.delete('NETBALLTICKET')
        if e.response.status_code == 401:
            raise AussieAddonsException('Login token has expired, '
                                        'please try again.')
        else:
            raise e
    return urllib.quote(video_token)
예제 #6
0
def get_matches():
    video_list = []
    data = fetch_url(config.MATCHES_URL)
    try:
        video_data = json.loads(data)
    except ValueError:
        utils.log('Failed to load JSON. Data is: {0}'.format(data))
        raise Exception('Failed to retrieve video data. Service may be '
                        'currently unavailable.')

    for match in video_data['matchList']['matches']:
        live_streams = match['liveStreams']

        # Use the thumb from the match article if available
        thumbnail = None
        if 'matchWrapArticle' in match:
            thumbnail = match['matchWrapArticle'].get('image')

        for ls in live_streams:
            # Only consider streams available in AU
            if 'AU' in [c['countryName'] for c in ls['streamCountriesList']]:
                name = "%s: %s v %s" % (match['series']['name'],
                                        match['homeTeam']['shortName'],
                                        match['awayTeam']['shortName'])
                video_list.append({
                    'video_id':
                    ls['id'],
                    'name':
                    name,
                    'thumbnail':
                    thumbnail or ls.get('thumbnailUrl')
                })

    return video_list
예제 #7
0
def make_series_list(params):
    utils.log('Showing series list')
    try:
        series_list = comm.get_series_list(params)
        series_list.sort()

        ok = True
        for s in series_list:
            url = '{0}?action=list_series&{1}'.format(sys.argv[0],
                                                      s.make_kodi_url())
            listitem = xbmcgui.ListItem(s.title,
                                        iconImage=s.get_thumb(),
                                        thumbnailImage=s.get_thumb())
            listitem.setInfo('video', {'plot': ''})

            # add the item to the media list
            ok = xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]),
                                             url=url,
                                             listitem=listitem,
                                             isFolder=True)

        xbmcplugin.endOfDirectory(handle=int(sys.argv[1]), succeeded=ok)
        xbmcplugin.setContent(handle=int(sys.argv[1]), content='tvshows')
    except Exception:
        utils.handle_error("Unable to fetch series listing")
예제 #8
0
def upload_log():
    """Upload our full Kodi log as a GitHub gist"""
    try:
        log_content = get_kodi_log()
    except Exception as e:
        utils.log("Failed to read log: %s" % e)
        return

    utils.log('Sending log file...')
    try:
        data = {
            "files": {
                "kodi.log": {
                    "content": log_content
                }
            }
        }
        response = urlopen(make_request(GIST_API_URL),
                           json.dumps(data).encode('utf-8'))
    except HTTPError as e:
        utils.log("Failed to save log: HTTPError %s" % e.code)
        return False
    except URLError as e:
        utils.log("Failed to save log: URLError %s" % e.reason)
        return False
    try:
        return json.load(response)['html_url']
    except Exception:
        utils.log("Failed to parse API response: %s" % response.read())
예제 #9
0
def get_series():
    series_list = []
    json_data = get_index()

    category_data = None
    for c in json_data['get']['response']['Menu']['children']:
        if c['name'] == 'Programs':
            category_data = c['children']
            break

    series_data = None
    for s in category_data:
        if s['name'] == 'Programs A-Z':
            series_data = s['children']
            break

    for entry in series_data:
        try:
            series = classes.Series()
            series.title = entry.get('name')
            series.id = entry.get('dealcodes')
            series.thumbnail = entry.get('thumbnail')
            series.num_episodes = int(entry.get('totalMpegOnly', 0))
            if series.num_episodes > 0:
                series_list.append(series)
        except Exception:
            utils.log('Error parsing entry: %s' % entry)
    return series_list
예제 #10
0
def get_media_auth_token(pai, video_id):
    """
    send our user token to get our embed token, including api key
    """
    url = config.MEDIA_AUTH_URL.format(code=video_id, pai=pai)

    try:
        data = comm.fetch_url(url, request_token=True)
        json_data = json.loads(data)
        if json_data.get('Fault'):
            raise AussieAddonsException(
                json_data.get('fault').get('faultstring'))
        media_auth_token = json_data.get('urlSigningToken')
    except requests.exceptions.HTTPError as e:
        utils.log('Error getting embed token. '
                  'Response: {0}'.format(e.response.text))
        cache.delete('AFLTOKEN')
        if e.response.status_code in [400, 401]:
            raise AussieAddonsException('Login token has expired, '
                                        'please try again.')
        elif e.response.status_code == 404:
            raise AussieAddonsException(
                'Unknown error, please wait a few moments and try again.')
        else:
            raise e
    return media_auth_token
def get_new_token(session):
    """send user login info and retrieve token for session"""
    utils.log('Retrieving new user token')
    username = addon.getSetting('LIVE_USERNAME')
    password = addon.getSetting('LIVE_PASSWORD')
    session.headers = config.BIGPOND_HEADERS
    url = config.BIGPOND_URL.format(username, password)
    auth_resp = session.post(url, logging=False)  # make sure not to log this!!
    auth_json = json.loads(auth_resp.text)
    artifact = auth_json['data'].get('artifactValue')

    session.headers = config.APIGEE_HEADERS
    url = config.APIGEE_URL.format(urllib.quote(artifact))
    token_resp = session.get(url)
    try:
        token_resp.raise_for_status()
    except requests.HTTPError as e:
        raise e
    token = json.loads(token_resp.text)
    session.headers.update({'ovs-token': token.get('tokenId'),
                            'ovs-uuid': token.get('uuid')})

    cookies = json.dumps(session.cookies.get_dict())
    expire = datetime.now() + timedelta(hours=2)
    cache.set('BIGPONDTOKEN', json.dumps(token))
    cache.set('BIGPONDCOOKIES', cookies)
    cache.set('BIGPONDEXPIRE', str(expire))
    return token
예제 #12
0
def play(url):
    try:
        addon = xbmcaddon.Addon()
        p = classes.Program()
        p.parse_xbmc_url(url)

        # Some programs don't have protected streams. 'Public' streams are
        # set in program.url, otherwise we fetch it separately
        if p.get_url():
            stream_info = {}
            stream_url = p.get_url()
        else:
            stream_info = comm.get_stream(p.id)
            stream_url = stream_info['url']

        bandwidth = addon.getSetting('BANDWIDTH')

        if bandwidth == '0':
            stream_url = stream_url.replace('&b=0-2000', '&b=400-600')
        elif bandwidth == '1':
            stream_url = stream_url.replace('&b=0-2000', '&b=900-1100')
        elif bandwidth == '2':
            stream_url = stream_url.replace('&b=0-2000', '&b=1400-1600')

        listitem = xbmcgui.ListItem(label=p.get_list_title(),
                                    iconImage=p.thumbnail,
                                    thumbnailImage=p.thumbnail,
                                    path=stream_url)
        listitem.setInfo('video', p.get_kodi_list_item())

        # Add subtitles if available
        if 'subtitles' in stream_info:
            sub_url = stream_info['subtitles']
            profile = addon.getAddonInfo('profile')
            path = xbmc.translatePath(profile).decode('utf-8')
            if not os.path.isdir(path):
                os.makedirs(path)
            subfile = xbmc.translatePath(
                os.path.join(path, 'subtitles.eng.srt'))
            if os.path.isfile(subfile):
                os.remove(subfile)
            try:
                data = urllib2.urlopen(sub_url).read()
                f = open(subfile, 'w')
                f.write(data)
                f.close()
                if hasattr(listitem, 'setSubtitles'):
                    # This function only supported from Kodi v14+
                    listitem.setSubtitles([subfile])
            except Exception:
                utils.log('Subtitles not available for this program')

        if hasattr(listitem, 'addStreamInfo'):
            listitem.addStreamInfo('audio', p.get_kodi_audio_stream_info())
            listitem.addStreamInfo('video', p.get_kodi_video_stream_info())

        xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, listitem=listitem)

    except Exception:
        utils.handle_error("Unable to play video")
예제 #13
0
def get_embed_token(login_ticket, videoId):
    """
    send our user token to get our embed token, including api key
    """
    data = create_nrl_userid_xml(userToken)
    url = config.EMBED_TOKEN_URL.format(videoId)
    try:
        req = sess.post(url,
                        data=data,
                        headers=config.YINZCAM_AUTH_HEADERS,
                        verify=False)
        xml = req.text[1:]
        try:
            tree = ET.fromstring(xml)
        except ET.ParseError as e:
            utils.log('Embed token response is: {0}'.format(xml))
            cache.delete('NRLTOKEN')
            raise e
        if tree.find('ErrorCode') is not None:
            utils.log('Errorcode found: {0}'.format(xml))
            raise AussieAddonsException()
        token = tree.find('Token').text
    except AussieAddonsException:
        cache.delete('NRLTOKEN')
        raise Exception('Login token has expired, please try again')
    return token
예제 #14
0
def make_category_list(url):
    utils.log("Making category list")
    try:
        params = utils.get_url(url)
        category = params.get('category')
        categories = comm.get_category(category)
        utils.log(categories)

        ok = True
        for c in categories.get('rows'):
            
            if c.get('layout', {}).get('itemType') == 'genre':
                genre = 'True'
            else:
                genre = 'False'
            
            url = "%s?%s" % (sys.argv[0], utils.make_url({
                                 'category': category,
                                 'genre': genre,
                                 'feed_url': c.get('feedUrl')}))
            
            thumbnail = c.get('thumbnail', '')
            listitem = xbmcgui.ListItem(label=c['name'],
                                        thumbnailImage=thumbnail)
            ok = xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]),
                                             url=url,
                                             listitem=listitem,
                                             isFolder=True)

        xbmcplugin.endOfDirectory(handle=int(sys.argv[1]), succeeded=ok)
        xbmcplugin.setContent(handle=int(sys.argv[1]), content='episodes')
    except Exception:
        utils.handle_error('Unable to build categories list')
def get_secure_token(secure_url, video_id):
    """send our embed token back with a few other url encoded parameters"""
    res = sess.get(secure_url)
    try:
        parsed_json = json.loads(res.text)
    except ValueError:
        utils.log('Failed to load JSON. Data is: {0}'.format(res.text))
        if '<html' in res.text:  # smart DNS redirects
            raise AussieAddonsException(
                'Failed to get authorization token. Please ensure any smart '
                'DNS service is disabled.')
        else:
            raise Exception('Failed to get authorization token.')
    if parsed_json.get('authorized') is False:
        raise AussieAddonsException('Failed to get authorization token: {0}'
                                    ''.format(parsed_json.get('message')))

    auth_data = parsed_json.get('authorization_data')

    utils.log('auth_data: %s' % auth_data)
    video = auth_data.get(video_id)

    if video.get('authorized') is False:
        raise AussieAddonsException('Failed to obtain secure token: {0}.\n'
                                    'Check your subscription is valid.'.format(
                                        video.get('message')))
    try:
        streams = video.get('streams')
        ios_token = streams[0]['url']['data']
        return base64.b64decode(ios_token)
    except Exception as e:
        raise AussieAddonsException('Failed to get stream URL: {0}'.format(e))
예제 #16
0
def get_series():
    series_list = []
    json_data = get_index()

    category_data = None
    for c in json_data['get']['response']['Menu']['children']:
        if c['name'] == 'Programs':
            category_data = c['children']
            break

    series_data = None
    for s in category_data:
        if s['name'] == 'Programs A-Z':
            series_data = s['children']
            break

    for entry in series_data:
        try:
            series = classes.Series()
            series.title = entry.get('name')
            series.id = entry.get('dealcodes')
            series.thumbnail = entry.get('thumbnail')
            series.num_episodes = int(entry.get('totalMpegOnly', 0))
            if series.num_episodes > 0:
                series_list.append(series)
        except Exception:
            utils.log('Error parsing entry: %s' % entry)
    return series_list
예제 #17
0
def get_programs_list(params):
    """Fetch the episode list for a given series"""
    series_url = params.get('url')
    program_list = []
    json_data = api_query(series_url)

    for item in json_data.get('items'):
        if item.get('title') == 'Shelf Container':
            for sub_item in item['items']:
                if not sub_item.get('items'):
                    continue
                for sub_item_2 in sub_item['items']:
                    for episode in sub_item_2.get('items'):
                        p = classes.Program()
                        p.title = episode['cardData']['image'].get('name')
                        p.thumb = episode['cardData']['image'].get('url')
                        p.description = episode['cardData'].get('synopsis')
                        p.url = episode['playerData'].get('videoUrl')
                        try:
                            # Try parsing the date
                            date = episode['infoPanelData'].get('airDate')
                            timestamp = time.mktime(
                                time.strptime(date, '%d &b %Y'))
                            p.date = datetime.date.fromtimestamp(timestamp)
                        except:
                            pass
                        utils.log('added program')
                        program_list.append(p)

    return program_list
예제 #18
0
def make_rounds(params):
    utils.log('Making rounds list...')
    try:
        season = comm.get_seasons(season=params.get('season'))
        rounds = reversed(season.get('rounds'))
        for r in rounds:
            name = r.get('name')
            round_id = r.get('roundId')
            season_id = r.get('seasonId')
            listitem = xbmcgui.ListItem(label=name)
            url = '{0}?name={1}&round_id={2}&season_id={3}'.format(
                sys.argv[0], name, round_id, season_id)

            # Add the item to the list
            ok = xbmcplugin.addDirectoryItem(
                handle=int(sys.argv[1]),
                url=url,
                listitem=listitem,
                isFolder=True,
                totalItems=len(season.get('rounds')))

        # send notification we're finished, successfully or unsuccessfully
        xbmcplugin.endOfDirectory(handle=int(sys.argv[1]), succeeded=ok)
    except Exception:
        utils.handle_error('Unable to make round list')
예제 #19
0
def get_bc_url(video):
    config_data = json.loads(fetch_url(config.CONFIG_URL, request_token=True))

    video.policy_key = [
        x for x in config_data['general']
        if x.get('id') == 'brightCovePK_premium'
    ][0].get('value')
    video.account_id = [
        x for x in config_data['general']
        if x.get('id') == 'brightCoveAccountId'
    ][0].get('value')

    if not video.policy_key:
        raise Exception("Can't retrieve brightcove policy key for {0}".format(
            video.account_id))
    data = fetch_url(config.BC_EDGE_URL.format(account_id=video.account_id,
                                               video_id=video.video_id),
                     headers={'BCOV-POLICY': video.policy_key})
    json_data = json.loads(data)
    src = None
    for source in json_data.get('sources'):
        if source.get('type') in [
                'application/vnd.apple.mpegurl', 'application/x-mpegURL'
        ]:
            src = source.get('src')
            if src.startswith('https'):
                break
    if not src:
        utils.log(json.dumps(json_data.get('sources')))
        raise Exception('Unable to locate video source.')
    return src
예제 #20
0
def get_stream_url(params, media_auth_token):
    bc_url = config.BC_URL.format(params.get('account_id'),
                                  params.get('video_id'))
    data = json.loads(
        fetch_url(bc_url, {'BCOV-POLICY': params.get('policy_key')}))
    src = None
    sources = data.get('sources')
    if len(sources) == 1:
        src = sources[0].get('src')
    else:
        for source in sources:
            tmp = source.get('src')
            if source.get('type') in [
                    'application/vnd.apple.mpegurl', 'application/x-mpegURL'
            ]:
                if tmp.startswith('https'):
                    src = tmp
                    break
    if not src:
        utils.log(data.get('sources'))
        raise Exception('Unable to locate video source.')
    if not media_auth_token:
        return str(src)
    else:
        src = sign_url(src, media_auth_token)
    return str(src)
def get_secure_token(secure_url, videoId):
    """send our embed token back with a few other url encoded parameters"""
    res = session.get(secure_url)
    data = res.text
    try:
        parsed_json = json.loads(data)
        for stream in parsed_json['authorization_data'][videoId]['streams']:
            if stream.get('delivery_type') == 'dash':
                dash_url = stream['url'].get('data')
                wv_lic = stream.get('widevine_server_path')
    except KeyError:
        utils.log('Parsed json data: {0}'.format(parsed_json))
        try:
            auth_msg = parsed_json['authorization_data'][videoId]['message']
            if auth_msg == 'unauthorizedlocation':
                country = parsed_json['user_info']['country']
                raise AussieAddonsException('Unauthorised location for '
                                            'streaming. '
                                            'Detected location is: {0}. '
                                            'Please check VPN/smart DNS '
                                            'settings and try again'
                                            ''.format(country))
        except Exception as e:
            raise e
    return {'dash_url': base64.b64decode(dash_url), 'wv_lic': wv_lic}
예제 #22
0
def make_index_list():
    print "hasdhsadhsa"
    utils.log('g2')
    try:
        utils.log('hello')
        index = comm.get_index()['contentStructure'].get('menu')
        ok = True
        for i in index:
            url = "%s?%s" % (sys.argv[0], utils.make_url({
                             'category': i}))
            listitem = xbmcgui.ListItem(i)
            # Add the program item to the list
            ok = xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]),
                                             url=url, listitem=listitem,
                                             isFolder=True)

        listitem = xbmcgui.ListItem(label='Settings')
        ok = xbmcplugin.addDirectoryItem(
            handle=int(sys.argv[1]),
            url="{0}?action=settings".format(sys.argv[0]),
            listitem=listitem,
            isFolder=False)

        xbmcplugin.endOfDirectory(handle=int(sys.argv[1]), succeeded=ok)
        xbmcplugin.setContent(handle=int(sys.argv[1]), content='episodes')
    except Exception:
        utils.handle_error('Unable to build index')
예제 #23
0
def make_rounds(params):
    utils.log('Making rounds list...')
    try:
        season = comm.get_seasons(season=params.get('season'))
        rounds = reversed(season.get('rounds'))
        for r in rounds:
            name = r.get('name')
            round_id = r.get('roundId')
            season_id = r.get('seasonId')
            listitem = xbmcgui.ListItem(label=name)
            url = '{0}?name={1}&round_id={2}&season_id={3}'.format(
                sys.argv[0], name, round_id, season_id)

            # Add the item to the list
            ok = xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]),
                                             url=url,
                                             listitem=listitem,
                                             isFolder=True,
                                             totalItems=len(
                                                 season.get('rounds')))

        # send notification we're finished, successfully or unsuccessfully
        xbmcplugin.endOfDirectory(handle=int(sys.argv[1]), succeeded=ok)
    except Exception:
        utils.handle_error('Unable to make round list')
예제 #24
0
def get_stream_url(video, media_auth_token):
    if not video.type == 'B':
        headers = {'authorization': 'basic {0}'.format(get_authorization())}
        data = fetch_url(config.STREAM_API_URL.format(video_id=video.video_id),
                         headers=headers)
        hls_url = json.loads(data).get('hls')
        return str(hls_url.replace('[[FILTER]]', 'nrl-vidset-ms'))
    else:
        bc_url = config.BC_URL.format(video.account_id, video.video_id)
        data = json.loads(
            fetch_url(bc_url, headers={'BCOV-POLICY': video.policy_key}))
        src = None
        sources = data.get('sources')
        if len(sources) == 1:
            src = sources[0].get('src')
        else:
            for source in sources:
                ext_ver = source.get('ext_x_version')
                src = source.get('src')
                if ext_ver == '4' and src:
                    if src.startswith('https'):
                        break
        if not src:
            utils.log(data.get('sources'))
            raise Exception('Unable to locate video source.')
        if not media_auth_token:
            return str(src)
        else:
            src = sign_url(src, media_auth_token)
            return src
def router(paramstring):
    """
    Router function that calls other functions
    depending on the provided paramstring
    :param paramstring:
    """
    params = dict(parse_qsl(paramstring))
    utils.log('Running addon with params: {0}'.format(params))
    if paramstring:
        if paramstring != 'content_type=video':
            if params['action'] == 'listcategories':
                if params['category'] == 'My Library':
                    menu.list_library(params)
                elif params['category'] == 'Settings':
                    addon.openSettings()
                else:
                    menu.make_content_list(params)
            elif params['action'] == 'librarylist':
                if params['category'] == 'movies':
                    menu.make_content_list(params)
                elif params['category'] == 'tv shows':
                    menu.list_series(params)
            elif params['action'] == 'listseries':
                menu.make_content_list(params)
            elif params['action'] == 'listplayable':
                play.play_video(params)
            elif params['action'] == 'cleartoken':
                telstra_auth.clear_token()
            elif params['action'] == 'reinstall_widevine_cdm':
                drmhelper.get_widevinecdm()
            elif params['action'] == 'reinstall_ssd_wv':
                drmhelper.get_ssd_wv()
    else:
        menu.list_categories()
예제 #26
0
def make_entries_list(url):
    utils.log('Making entries list')
    try:
        params = utils.get_url(url)
        programs = comm.get_entries(params['entries_url'])

        ok = True
        for p in sorted(programs):
            listitem = xbmcgui.ListItem(label=p.get_list_title(),
                                        iconImage=p.get_thumbnail(),
                                        thumbnailImage=p.get_thumbnail())
            listitem.setInfo('video', p.get_kodi_list_item())
            listitem.setProperty('IsPlayable', 'true')

            if hasattr(listitem, 'addStreamInfo'):
                listitem.addStreamInfo('audio', p.get_kodi_audio_stream_info())
                listitem.addStreamInfo('video', p.get_kodi_video_stream_info())

            # Build the URL for the program, including the list_info
            url = "%s?play=true&%s" % (sys.argv[0], p.make_xbmc_url())

            # Add the program item to the list
            ok = xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]),
                                             url=url,
                                             listitem=listitem,
                                             isFolder=False,
                                             totalItems=len(programs))

        xbmcplugin.endOfDirectory(handle=int(sys.argv[1]), succeeded=ok)
        xbmcplugin.setContent(handle=int(sys.argv[1]), content='episodes')
    except Exception:
        utils.handle_error('Unable to fetch program list')
예제 #27
0
def get_secure_token(secure_url, videoId):
    """
    send our embed token back with a few other url encoded parameters
    """
    res = sess.get(secure_url)
    data = res.text
    try:
        parsed_json = json.loads(data)
        token = (parsed_json['authorization_data'][videoId]['streams'][0]
                 ['url']['data'])
    except KeyError:
        utils.log('Parsed json data: {0}'.format(parsed_json))
        try:
            auth_msg = parsed_json['authorization_data'][videoId]['message']
            if auth_msg == 'unauthorized location':
                country = parsed_json['user_info']['country']
                raise AussieAddonsException('Unauthorised location for '
                                            'streaming. '
                                            'Detected location is: {0}. '
                                            'Please check VPN/smart DNS '
                                            'settings '
                                            ' and try again'.format(country))
        except Exception as e:
            raise e
    return base64.b64decode(token)
예제 #28
0
def get_collection_from_feed(params):
    keyword = params.get('collection_id')
    utils.log('Getting collection from feed ({0})'.format(params.get('title')))
    feed = get_cached_feed(
        config.API_BASE_URL.format(path='/v2/collection/{0}'.format(keyword)))
    collection = parse.parse_programme_from_feed(feed, params)
    return collection
예제 #29
0
def make_entries_list(url):
    utils.log('Making entries list')
    try:
        params = utils.get_url(url)
        programs = comm.get_entries(params['feed_url'])

        ok = True
        for p in sorted(programs):
            listitem = xbmcgui.ListItem(label=p.get_list_title(),
                                        iconImage=p.get_thumbnail(),
                                        thumbnailImage=p.get_thumbnail())
            if type(p) is classes.Program:
                listitem.setInfo('video', p.get_kodi_list_item())
                listitem.setProperty('IsPlayable', 'true')

            #if hasattr(listitem, 'addStreamInfo'):
                listitem.addStreamInfo('audio', p.get_kodi_audio_stream_info())
                listitem.addStreamInfo('video', p.get_kodi_video_stream_info())

                # Build the URL for the program, including the list_info
                url = "%s?play=true&%s" % (sys.argv[0], p.make_xbmc_url())
            else:
                url = "%s?%s" % (sys.argv[0], utils.make_url({
                                 'feed_url': p.feed_url}))
            # Add the program item to the list
            isFolder = type(p) is classes.Series
            ok = xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]), url=url,
                                             listitem=listitem, isFolder=isFolder,
                                             totalItems=len(programs))

        xbmcplugin.endOfDirectory(handle=int(sys.argv[1]), succeeded=ok)
        xbmcplugin.setContent(handle=int(sys.argv[1]), content='episodes')
    except Exception:
        utils.handle_error('Unable to fetch program list')
def get_secure_token(secure_url, video_id):
    """send our embed token back with a few other url encoded parameters"""
    res = sess.get(secure_url)
    try:
        parsed_json = json.loads(res.text)
    except ValueError:
        utils.log('Failed to load JSON. Data is: {0}'.format(res.text))
        if '<html' in res.text:  # smart DNS redirects
            raise AussieAddonsException(
                'Failed to get authorization token. Please ensure any smart '
                'DNS service is disabled.')
        else:
            raise Exception('Failed to get authorization token.')
    if parsed_json.get('authorized') is False:
        raise AussieAddonsException(
            'Failed to get authorization token: {0}'
            ''.format(parsed_json.get('message')))

    auth_data = parsed_json.get('authorization_data')

    utils.log('auth_data: %s' % auth_data)
    video = auth_data.get(video_id)

    if video.get('authorized') is False:
        raise AussieAddonsException(
            'Failed to obtain secure token: {0}.\n'
            'Check your subscription is valid.'.format(video.get('message')))
    try:
        streams = video.get('streams')
        stream_url = base64.b64decode(streams[0]['url']['data'])
        widevine_url = streams[0].get('widevine_server_path')
        return {'stream_url': stream_url, 'widevine_url': widevine_url}
    except Exception as e:
        raise AussieAddonsException(
            'Failed to get stream URL: {0}'.format(e))
예제 #31
0
def get_stream_url(hn, path):
    with session.Session() as sess:
        video_url = config.API_BASE_URL.format(path='/v2{0}'.format(path))
        utils.log("Fetching stream URL: {0}".format(video_url))
        video_data = sess.get(video_url).text
        video_json = json.loads(video_data)
        if video_json.get('playable') is False:
            return {
                'msg': video_json.get('playableMessage'),
                'availability': video_json.get('availability')
            }
        sess.headers = {'User-Agent': config.USER_AGENT}
        for playlist in video_json['_embedded']['playlist']:
            if playlist.get('type') not in ['program', 'livestream']:
                continue
            if 'hls' in playlist.get('streams'):
                hls_streams = playlist['streams'].get('hls')
                stream_url_base = hls_streams.get(
                    '720', hls_streams.get('sd', hls_streams.get('sd-low')))
            if stream_url_base:
                captions_url = playlist.get('captions', {}).get('src-vtt')
                break
        akamai_auth = get_auth(hn, sess)
        request = sess.get(stream_url_base, params={'hdnea': akamai_auth})
        cookies = cookies_to_string(request.cookies)
        stream_url = '{0}|User-Agent={1}&Cookie={2}'.format(
            request.url, quote_plus(config.USER_AGENT), quote_plus(cookies))

    return {'stream_url': stream_url, 'captions_url': captions_url}
예제 #32
0
def make_category_list(url):
    utils.log("Making category list")
    try:
        params = utils.get_url(url)
        categories = comm.get_category(params['category'])

        ok = True
        if 'children' in categories:
            for c in categories.get('children', []):
                if 'children' in c:
                    url = "%s?%s" % (sys.argv[0], utils.make_url({
                                     'category': params['category'],
                                     'section': c['name']}))
                elif 'url' in c:
                    url = "%s?%s" % (sys.argv[0], utils.make_url({
                                     'entries_url': c['url']}))
                else:
                    continue

                # If no thumbnail, make it an empty string as None makes
                # XBMC v12 with a TypeError must be unicode or str
                thumbnail = c.get('thumbnail', '')
                listitem = xbmcgui.ListItem(label=c['name'],
                                            thumbnailImage=thumbnail)
                ok = xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]),
                                                 url=url,
                                                 listitem=listitem,
                                                 isFolder=True)
        else:
            # 'Coming soon' has no children
            jsonurl = categories['url']
            programs = comm.get_entries(jsonurl)
            for p in sorted(programs):
                thumbnail = p.get_thumbnail()
                listitem = xbmcgui.ListItem(label=p.get_list_title(),
                                            iconImage=thumbnail,
                                            thumbnailImage=thumbnail)
                listitem.setInfo('video', p.get_kodi_list_item())

                if hasattr(listitem, 'addStreamInfo'):
                    listitem.addStreamInfo('audio',
                                           p.get_kodi_audio_stream_info())
                    listitem.addStreamInfo('video',
                                           p.get_kodi_video_stream_info())

                # Build the URL for the program, including the list_info
                url = "%s?play=true&%s" % (sys.argv[0], p.make_xbmc_url())

                # Add the program item to the list
                ok = xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]),
                                                 url=url,
                                                 listitem=listitem,
                                                 isFolder=False,
                                                 totalItems=len(programs))

        xbmcplugin.endOfDirectory(handle=int(sys.argv[1]), succeeded=ok)
        xbmcplugin.setContent(handle=int(sys.argv[1]), content='episodes')
    except Exception:
        utils.handle_error('Unable to build categories list')
예제 #33
0
def get_collections_from_feed(params):
    utils.log('Getting collections from feed ({0})'.format(
        params.get('category')))
    feed = get_cached_feed(
        config.API_BASE_URL.format(
            path='/v2{0}'.format(params.get('category'))))
    collects = parse.parse_collections_from_feed(feed, params)
    return collects
예제 #34
0
def save_last_error_report(error):
    """Save a copy of our last error report"""
    try:
        rfile = os.path.join(utils.get_file_dir(), 'last_report_error.txt')
        with open(rfile, 'w') as f:
            f.write(error)
    except Exception:
        utils.log("Error writing error report file")
예제 #35
0
def parse_m3u8(data, m3u8_path, qual=-1, live=False):
    """
    Parse the retrieved m3u8 stream list into a list of dictionaries
    then return the url for the highest quality stream.
    """
    ver = 0
    if '#EXT-X-VERSION:3' in data:
        ver = 3
        data.remove('#EXT-X-VERSION:3')
    if '#EXT-X-VERSION:4' in data:
        ver = 4
        data.remove('#EXT-X-VERSION:4')
    if '#EXT-X-INDEPENDENT-SEGMENTS' in data:
        data.remove('#EXT-X-INDEPENDENT-SEGMENTS')
    count = 1
    m3u_list = []
    while count < len(data):
        if ver == 3 or ver == 0:
            line = data[count]
            line = line.strip('#EXT-X-STREAM-INF:')
            line = line.strip('PROGRAM-ID=1,')
            if 'CODECS' in line:
                line = line[:line.find('CODECS')]
            if line.endswith(','):
                line = line[:-1]
            line = line.strip()
            line = line.split(',')
            linelist = [i.split('=') for i in line]
            if live:
                url = urlparse.urljoin(m3u8_path, data[count + 1])
            else:
                url = data[count + 1]
            linelist.append(['URL', url])
            m3u_list.append(dict((i[0], i[1]) for i in linelist))
            count += 2

        if ver == 4:
            line = data[count]
            line = line.strip('#EXT-X-STREAM-INF:')
            line = line.strip('PROGRAM-ID=1,')
            values = line.split(',')
            for value in values:
                if value.startswith('BANDWIDTH'):
                    bw = value
                elif value.startswith('RESOLUTION'):
                    res = value
            url = urlparse.urljoin(m3u8_path, data[count + 1])
            m3u_list.append(dict([bw.split('='),
                                  res.split('='), ['URL', url]]))
            count += 3

    sorted_m3u_list = sorted(m3u_list, key=lambda k: int(k['BANDWIDTH']))
    utils.log('Available streams are: {0}'.format(sorted_m3u_list))
    try:
        stream = sorted_m3u_list[qual]['URL']
    except IndexError:  # less streams than we expected - go with highest
        stream = sorted_m3u_list[-1]['URL']
    return stream
예제 #36
0
def parse_m3u8_streams(data, live, secure_token_url):
    """
    Parse the retrieved m3u8 stream list into a list of dictionaries
    then return the url for the highest quality stream. Different
    handling is required of live m3u8 files as they seem to only contain
    the destination filename and not the domain/path.
    """
    if live:
        qual = int(addon.getSetting('LIVEQUALITY'))
        if qual == config.MAX_LIVEQUAL:
            qual = -1
        # fix for values too high from previous API config
        if qual > config.MAX_LIVEQUAL:
            addon.setSetting('LIVEQUALITY', str(config.MAX_LIVEQUAL))
            qual = -1
    else:
        qual = int(addon.getSetting('REPLAYQUALITY'))
        if qual == config.MAX_REPLAYQUAL:
            qual = -1
        # fix for values too high from previous API config
        if qual > config.MAX_REPLAYQUAL:
            addon.setSetting('REPLAYQUALITY', str(config.MAX_REPLAYQUAL))
            qual = -1

    if '#EXT-X-VERSION:3' in data:
        data.remove('#EXT-X-VERSION:3')
    count = 1
    m3u_list = []
    prepend_live = secure_token_url[:secure_token_url.find('index-root')]
    while count < len(data):
        line = data[count]
        line = line.strip('#EXT-X-STREAM-INF:')
        line = line.strip('PROGRAM-ID=1,')
        line = line[:line.find('CODECS')]

        if line.endswith(','):
            line = line[:-1]

        line = line.strip()
        line = line.split(',')
        linelist = [i.split('=') for i in line]

        if not live:
            linelist.append(['URL', data[count + 1]])
        else:
            linelist.append(['URL', prepend_live + data[count + 1]])

        m3u_list.append(dict((i[0], i[1]) for i in linelist))
        count += 2

    sorted_m3u_list = sorted(m3u_list, key=lambda k: int(k['BANDWIDTH']))
    try:
        stream = sorted_m3u_list[qual]['URL']
    except IndexError as e:
        utils.log('Quality setting: {0}'.format(qual))
        utils.log('Sorted m3u8 list: {0}'.format(sorted_m3u_list))
        raise e
    return stream
예제 #37
0
def create_seasons_list(seasons, thumb):
    listing = []
    for entry in seasons.get('feeds'):
        try:
            s = create_season(entry, thumb)
            listing.append(s)
        except Exception:
            utils.log('Error parsing season entry')
    return listing
    def getData(self,
                url,
                headers={},
                name=None,
                noCache=False,
                expiry=None,
                data=None):

        now = datetime.datetime.now()

        if not headers or not headers.get('User-Agent'):
            headers['User-Agent'] = USER_AGENT

        if noCache or not name:
            data = CacheObj.fetch_url(url=url, headers=headers)
        if not name:
            return data

        if not data:
            rawData = self.win.getProperty('%s|%s' % (name, url))
            if rawData:
                try:
                    cachedData = eval(rawData)
                    if not isinstance(expiry, datetime.timedelta):
                        expiry = CacheObj.maxTTL
                    if cachedData[0] + CacheObj.minTTL < now:
                        bgFetch = Thread(target=self.getData,
                                         kwargs=dict(url=url,
                                                     headers=headers,
                                                     name=name,
                                                     noCache=True))
                        bgFetch.start()
                    if cachedData[0] + expiry > now:
                        return cachedData[1]
                except Exception as e:
                    utils.log('Error with eval of cached data: {0}'.format(e))

            data = CacheObj.fetch_url(url=url, headers=headers)

        cachedData = (now, data)
        self.win.setProperty('%s|%s' % (name, url), repr(cachedData))

        rawURLs = self.win.getProperty('%s|urls' % name)
        urls = eval(rawURLs) if rawURLs else deque()

        if url in urls:
            urls.remove(url)
        urls.append(url)

        if len(urls) > CacheObj.maxEntries:
            oldUrl = urls.popleft()
            self.win.clearProperty('%s|%s' % (name, oldUrl))

        self.win.setProperty('%s|urls' % name, repr(urls))

        return cachedData[1]
예제 #39
0
def get_category(category):
    """Fetch a given top level category from the index.

    This is usually programs and movies.
    """
    utils.log("Fetching category: %s" % category)
    index = get_index()
    index2 = index.get('contentStructure')
    index3 = index2.get('screens')
    return index.get('contentStructure').get('screens').get(category)
def fetch_session_id(url, data):
    """send http POST and return the json response data"""
    data = urllib.urlencode(data)
    sess.headers = config.HEADERS
    comm.update_token(sess)
    res = sess.post(url, data)
    try:
        res.raise_for_status()
    except requests.exceptions.HTTPError as e:
        utils.log(e.response.text)
        raise Exception(e)
    return res.text
def fetch_url(url, headers={}):
    """
    Use custom session to grab URL and return the text
    """
    with session.Session(force_tlsv1=True) as sess:
        res = sess.get(url, headers=headers)
        try:
            data = json.loads(res.text)
            return data
        except ValueError as e:
            utils.log('Error parsing JSON, response is {0}'.format(res.text))
            raise e
예제 #42
0
def get_stream_url(hn, url):
    utils.log("Fetching stream URL: {0}".format(url))
    with session.Session() as sess:
        sess.headers = {'User-Agent': config.USER_AGENT}
        akamai_auth = get_auth(hn, sess)
        akamai_url = "{0}?hdnea={1}".format(url, akamai_auth)
        request = sess.get(akamai_url)
        cookies = cookies_to_string(request.cookies)
        stream_url = '{0}|User-Agent={1}&Cookie={2}'.format(
            akamai_url, urllib.quote(config.USER_AGENT), urllib.quote(cookies))

    return stream_url
예제 #43
0
def fetch_auth_token():
    """Perform a HTTP POST to secure server to fetch a token"""
    utils.log('Fetching new auth token')
    try:
        sess = session.Session()
        request = sess.post(config.token_url)
        request.raise_for_status()
        data = json.loads(request.text)
        token = data['sessiontoken']['response']['token']
        return token
    except Exception as e:
        raise Exception('Failed to fetch SBS streaming token: %s' % e)
예제 #44
0
def fetch_related_list(urls, listobj):
    utils.log('Downloading episode listings (%d) ...' % len(urls))
    threads = []
    listobj.extend([None for x in range(len(urls))])
    for index, url in enumerate(urls):
        thread = threading.Thread(target=fetch_related,
                                  args=(url, listobj, index))
        thread.daemon = True
        thread.start()
        threads.append(thread)

    for thread in threads:
        thread.join()
def parse_m3u8_streams(data, live, secure_token_url):
    """Parse m3u8 stream

    Parse the retrieved m3u8 stream list into a list of dictionaries
    then return the url for the highest quality stream. Different
    handling is required of live m3u8 files as they seem to only contain
    the destination filename and not the domain/path.
    """

    if live:
        qual = int(xbmcaddon.Addon().getSetting('LIVE_QUALITY'))
        if qual == config.MAX_LIVE_QUAL:
            qual = -1
    else:
        qual = int(xbmcaddon.Addon().getSetting('REPLAYQUALITY'))
        if qual == config.MAX_REPLAY_QUAL:
            qual = -1

    m3u_list = []
    base_url = secure_token_url[:secure_token_url.rfind('/') + 1]
    base_domain = secure_token_url[:secure_token_url.find('/', 8) + 1]
    m3u8_lines = iter(data)
    for line in m3u8_lines:
            stream_inf = '#EXT-X-STREAM-INF:'
            if line.startswith(stream_inf):
                line = line[len(stream_inf):]
            else:
                continue

            csv_list = re.split(',(?=(?:(?:[^"]*"){2})*[^"]*$)', line)
            linelist = [i.split('=') for i in csv_list]

            uri = next(m3u8_lines)

            if uri.startswith('/'):
                linelist.append(['URL', base_domain + uri])
            elif uri.find('://') == -1:
                linelist.append(['URL', base_url + uri])
            else:
                linelist.append(['URL', uri])
            m3u_list.append(dict((i[0], i[1]) for i in linelist))
    sorted_m3u_list = sorted(m3u_list, key=lambda k: int(k['BANDWIDTH']))
    try:
        stream = sorted_m3u_list[qual]['URL']
    except IndexError as e:
        utils.log('Quality setting: {0}'.format(qual))
        utils.log('Sorted m3u8 list: {0}'.format(sorted_m3u_list))
        raise e
    return stream
예제 #46
0
def get_entries(url):
    resp = fetch_cache_url(url)
    json_data = json.loads(resp)

    programs_list = []
    for entry in json_data.get('itemListElement'):
        try:
            if entry.get('type') == 'TVSeries':
                p = create_series(entry)
            else:
                p = create_program(entry)
            programs_list.append(p)
        except Exception:
            utils.log('Error parsing entry')

    return programs_list
예제 #47
0
def get_categories(url):
    # TODO(andy): Switch to use this function
    resp = fetch_cache_url(url)
    json_data = json.loads(resp)

    series_list = []
    for entry in json_data['entries']:
        try:
            series = classes.Series()
            series.title = entry.get('name')
            series.id = entry.get('dealcodes')
            series.thumbnail = entry.get('thumbnail')
            series.num_episodes = int(entry.get('totalMpegOnly', 0))
            if series.num_episodes > 0:
                series_list.append(series)
        except Exception:
            utils.log('Error parsing entry: %s' % entry)
    return series_list
예제 #48
0
def router(paramstring):
    """
    Router function that calls other functions
    depending on the provided paramstring
    :param paramstring:
    """
    params = dict(parse_qsl(paramstring))
    utils.log('Running with params: {0}'.format(params))
    if params:
        if params['action'] == 'listcategories':
            if params['category'] == 'Live Matches':
                menu.list_matches(params, live=True)
            elif params['category'] == 'Settings':
                addon.openSettings()
            else:
                menu.list_videos(params)
        elif params['action'] in ['listvideos', 'listmatches']:
            play.play_video(params)
        elif params['action'] == 'clearticket':
            ooyalahelper.clear_ticket()
    else:
        menu.list_categories()
def get_embed_token(user_token, video_id):
    """send our user token to get our embed token, including api key"""
    try:
        comm.update_token(sess)
        embed_token_url = config.EMBED_TOKEN_URL.format(user_token, video_id)
        utils.log("Fetching embed token: {0}".format(embed_token_url))
        try:
            res = sess.get(embed_token_url)
        except requests.exceptions.SSLError:
            cache.delete('AFLTOKEN')
            raise AussieAddonsException(
                'Your version of Kodi is too old to support live streaming. '
                'Please upgrade to the latest version.')
    except requests.exceptions.HTTPError as e:
        if subscription_type == 0:  # paid afl.com.au/linked
            cache.delete('AFLTOKEN')
            raise AussieAddonsException(
                'Paid or linked subscription not found for supplied username '
                'and password. Please check the subscription type in settings '
                'is correct or your subscription has been linked to your '
                'Telstra ID in the Android/iOS app')
        elif subscription_type in [1, 3]:  # free/mobile sub
            cache.delete('AFLTOKEN')
            utils.log(e.response.text)
            if e.response.status_code == 400:
                raise AussieAddonsException(
                    'Stored login token has expired, please try to play this '
                    'item again. If this error persists please submit an '
                    'issue on our github (github.com/aussieaddons/plugin.'
                    'video.afl-video')
            else:
                raise e
        else:  # in-app purchase/manual
            raise AussieAddonsException(
                'mis-uuid token is invalid, please check the token in '
                'the settings is correct and try again')

    data = json.loads(res.text)
    return urllib.quote(data.get('token'))
def fetch_bc_url(url, headers={}):
    """
    Use fetch_url and catch Brightcove API errors
    """
    try:
        data = fetch_url(url=url, headers=headers)
        return data
    except requests.exceptions.HTTPError as e:
        utils.log(e.response.text)
        if e.response.status_code == 403:
            try:
                error_data = json.loads(e.response.text)
                if error_data[0].get('error_subcode') == 'CLIENT_GEO':
                    raise AussieAddonsException(
                        'Content is geoblocked, your detected country is: {0}'
                        ''.format(error_data[0].get('client_geo')))
                else:
                    raise e
            except IndexError:
                raise e
            except ValueError:
                raise e
        else:
            raise e
예제 #51
0
def make_categories_list():
    utils.log('Showing category list')
    try:
        categories_list = comm.get_categories()
        categories_list.sort()
        categories_list.insert(0, classes.Category(title='Live TV'))
        categories_list.append(classes.Category(title='Settings'))

        for c in categories_list:
            url = '{0}?action=list_categories&{1}'.format(sys.argv[0],
                                                          c.make_kodi_url())
            listitem = xbmcgui.ListItem(label=c.title,
                                        iconImage=c.get_thumb(),
                                        thumbnailImage=c.get_thumb())

            ok = xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]),
                                             url=url,
                                             listitem=listitem,
                                             isFolder=True)

        xbmcplugin.endOfDirectory(handle=int(sys.argv[1]), succeeded=ok)
        xbmcplugin.setContent(handle=int(sys.argv[1]), content='tvshows')
    except Exception:
        utils.handle_error("Unable to show category listing")
예제 #52
0
def get_series_from_feed(series_url, ep_count):
    utils.log('Fetching series from feed')
    feed = get_feed(series_url)
    return parse.parse_programs_from_feed(feed, ep_count)
예제 #53
0
def get_programme_from_feed(keyword):
    keyword = validate_category(keyword)
    utils.log('Getting programme from feed (%s)' % keyword)
    feed = get_feed(keyword)
    shows = parse.parse_programme_from_feed(feed, keyword)
    return shows
예제 #54
0
import hmac
import json
import parse
import requests
import threading
import time
import urllib

from aussieaddonscommon import exceptions
from aussieaddonscommon import session
from aussieaddonscommon import utils

try:
    import StorageServer
except ImportError:
    utils.log('script.common.plugin.cache not found!')
    import storageserverdummy as StorageServer

cache = StorageServer.StorageServer(utils.get_addon_id(), 1)


def fetch_url(url, headers=None):
    """Simple function that fetches a URL using requests."""
    with session.Session() as sess:
        if headers:
            sess.headers.update(headers)
        request = sess.get(url)
        try:
            request.raise_for_status()
        except Exception as e:
            # Just re-raise for now
예제 #55
0
import base64
import classes
import config
import datetime
import json
import uuid

from aussieaddonscommon import session
from aussieaddonscommon import utils

from bs4 import BeautifulSoup

try:
    import StorageServer
except ImportError:
    utils.log("script.common.plugin.cache not found!")
    import storageserverdummy as StorageServer

cache = StorageServer.StorageServer(utils.get_addon_id(), 1)


def fetch_url(url, headers=None):
    """Simple function that fetches a URL using requests."""
    with session.Session(force_tlsv1=True) as sess:
        if headers:
            sess.headers.update(headers)
        request = sess.get(url)
        try:
            request.raise_for_status()
        except Exception as e:
            # Just re-raise for now
예제 #56
0
        programs.make_programs_list(params_str)
    elif 'category' in params:
        if params['category'] == 'settings':
            xbmcaddon.Addon().openSettings()
        else:
            series.make_series_list(params_str)
    elif 'action' in params:
        if params['action'] == 'sendreport':
            utils.user_report()
        elif params['action'] == 'update_ia':
            try:
                import drmhelper
                addon = drmhelper.get_addon(drm=False)
                if not drmhelper.is_ia_current(addon, latest=True):
                    if xbmcgui.Dialog().yesno(
                        'Upgrade?', ('Newer version of inputstream.adaptive '
                                     'available ({0}) - would you like to '
                                     'upgrade to this version?'.format(
                                        drmhelper.get_latest_ia_ver()))):
                        drmhelper.get_ia_direct(update=True, drm=False)
                else:
                    ver = addon.getAddonInfo('version')
                    utils.dialog_message('Up to date: Inputstream.adaptive '
                                         'version {0} installed and enabled.'
                                         ''.format(ver))
            except ImportError:
                utils.log("Failed to import drmhelper")
                utils.dialog_message('DRM Helper is needed for this function. '
                                     'For more information, please visit: '
                                     'http://aussieaddons.com/drm')
def get_user_token():
    """Send user login info and retrieve token for session"""
    # in-app purchase/manual
    if subscription_type == 2:
        iap_token = addon.getSetting('IAP_TOKEN').lower()
        try:
            int(iap_token, 16)
        except ValueError:
            raise AussieAddonsException(
                'mis-uuid token must be 32 characters in length, and only '
                'contain numbers 0-9 and letters a-f')
        if len(iap_token) != 32:
            raise AussieAddonsException(
                'mis-uuid token must be 32 characters in length, and only '
                'contain numbers 0-9 and letters a-f')
        token = 'mis-uuid-{0}'.format(iap_token)
        utils.log('Using manual token: {0}******'.format(token[:-6]))
        return token

    stored_token = cache.get('AFLTOKEN')
    if stored_token:
        utils.log('Using token: {0}******'.format(stored_token[:-6]))
        return stored_token

    if addon.getSetting('LIVE_SUBSCRIPTION') == 'true':
        username = addon.getSetting('LIVE_USERNAME')
        password = addon.getSetting('LIVE_PASSWORD')

        if subscription_type == 1:  # free subscription
            token = telstra_auth.get_token(username, password)
        elif subscription_type == 3:  # mobile activated subscription
            token = telstra_auth.get_mobile_token()
        else:  # paid afl.com.au
            login_data = {'userIdentifier': addon.getSetting('LIVE_USERNAME'),
                          'authToken': addon.getSetting('LIVE_PASSWORD'),
                          'userIdentifierType': 'EMAIL'}
            login_json = fetch_session_id(config.LOGIN_URL, login_data)
            data = json.loads(login_json)
            utils.log(data)
            if data.get('responseCode') != 0:
                raise AussieAddonsException('Invalid Telstra ID login/'
                                            'password for paid afl.com.au '
                                            '/ linked subscription.')
            session_id = data['data'].get('artifactValue')

            try:
                sess.headers.update({'Authorization': None})
                encoded_session_id = urllib.quote(session_id)
                session_url = config.SESSION_URL.format(encoded_session_id)
                res = sess.get(session_url)
                data = json.loads(res.text)
                token = data.get('uuid')

            except requests.exceptions.HTTPError as e:
                utils.log(e.response.text)
                raise e
        cache.set('AFLTOKEN', token)
        utils.log('Using token: {0}******'.format(token[:-6]))
        return token
    else:
        raise AussieAddonsException('AFL Live Pass subscription is required '
                                    'for this content. Please open the '
                                    'add-on settings to enable and configure.')
예제 #58
0
def get_section(category, section):
    utils.log("Fetching section: %s" % section)
    category = get_category(category)
    for s in category['children']:
        if s['name'] == section:
            return s
예제 #59
0
def get_program(params):
    """Fetch the program information and stream URL for a given program ID"""
    utils.log('Fetching program information for: {0}'.format(
        params.get('title')))

    program = classes.Program()
    program.parse_xbmc_url(sys.argv[2])
    program_url = program.format_url(params.get('url'))
    data = fetch_url(program_url)
    dash_preferred = ADDON.getSetting('dash_enabled') == 'true'

    try:
        program_data = json.loads(data)
    except Exception:
        utils.log("Bad program data: %s" % program_data)
        raise Exception("Error decoding program information.")

    if 'text_tracks' in program_data.get('media'):
        if len(program_data['media'].get('text_tracks')) == 0:
            utils.log("No subtitles available for this program")
        else:
            utils.log("Subtitles are available for this program")
            program.subtitle = (program_data['media']['text_tracks'][0]
                                .get('src'))

    for source in program_data['media'].get('sources'):
        # Get DASH URL
        if source.get('type') == 'application/dash+xml':
            if 'hbbtv' in source.get('src'):
                continue
            program.dash_url = source.get('src')
            program.dash_preferred = dash_preferred
            utils.log('Found DASH stream: {0}'.format(program.dash_url))
            if 'key_systems' in source:
                if 'com.widevine.alpha' in source['key_systems']:
                    program.drm_key = (source['key_systems']
                                             ['com.widevine.alpha']
                                             ['license_url'])
                    utils.log('DASH stream using Widevine')
        # Get HLS URL
        elif source.get('type') in ['application/x-mpegURL',
                                    'application/vnd.apple.mpegurl']:
            if 'key_systems' in source:
                continue
            if source.get('ext_x_version') != '5':
                program.hls_url = source.get('src')
                utils.log('Found HLS stream: {0}'.format(program.hls_url))
    return program
예제 #60
0
def fetch_cache_token():
    """Get the token from cache is possible"""
    utils.log('Fetching cached token if possible')
    return cache.cacheFunction(fetch_auth_token)