예제 #1
0
def playlist(output, **kwargs):
    data = api.panel(panel_id=CHANNELS_PANEL)

    try:
        chnos = Session().get(CHNO_URL).json()
    except:
        chnos = {}

    with codecs.open(output, 'w', encoding='utf8') as f:
        f.write(u'#EXTM3U\n')

        for row in data.get('contents', []):
            if row['data']['type'] != 'live-linear':
                continue

            chid = row['data']['playback']['info']['assetId']
            chno = chnos.get(chid) or ''

            f.write(
                u'#EXTINF:-1 tvg-id="{id}" tvg-chno="{channel}" channel-id="{channel}" tvg-logo="{logo}",{name}\n{path}\n'
                .format(id=chid,
                        channel=chno,
                        logo=row['data']['contentDisplay']['images']
                        ['tile'].replace('${WIDTH}', str(768)),
                        name=row['data']['playback']['info']['title'],
                        path=plugin.url_for(play,
                                            id=chid,
                                            play_type=PLAY_FROM_START,
                                            _is_live=True)))
예제 #2
0
    def new_session(self):
        self.logged_in = False
        self._session = Session(headers=HEADERS)
        self._set_authentication()

        self._default_params = DEFAULT_PARAMS
        self._default_params['signedUp'] = False  #self.logged_in
예제 #3
0
    def new_session(self):
        self.logged_in = False

        self._session = Session(HEADERS, base_url=API_URL)

        if userdata.get('singtel_tv_no'):
            self.logged_in = True
예제 #4
0
def playlist(output, **kwargs):
    data = api.panel(CHANNELS_PANEL)

    try:
        chnos = Session().get(CHNO_URL).json()
    except:
        chnos = {}

    with codecs.open(output, 'w', encoding='utf8') as f:
        f.write(u'#EXTM3U\n')

        for row in data.get('contents', []):
            asset = row['data']['asset']

            if row['contentType'] != 'video':
                continue

            chid = asset['id']
            chno = chnos.get(chid) or ''

            f.write(
                u'#EXTINF:-1 tvg-id="{id}" tvg-chno="{channel}" channel-id="{channel}" tvg-logo="{logo}",{name}\n{path}\n'
                .format(id=chid,
                        channel=chno,
                        logo=_get_image(asset, 'video', 'thumb'),
                        name=asset['title'],
                        path=plugin.url_for(play,
                                            id=chid,
                                            play_type=PLAY_FROM_START,
                                            _is_live=True)))
예제 #5
0
    def new_session(self):
        self.logged_in = False
        self._session = Session(headers=HEADERS, base_url=BASE_URL)
        self.logged_in = userdata.get('key', None) != None

        #LEGACY
        userdata.delete('token')
        userdata.delete('user_id')
예제 #6
0
    def new_session(self):
        self.logged_in = False
        self._auth_headers = {}
        self._config = {}

        self._session = Session(headers=HEADERS)
        self._session.after_request = self._check_response

        self._set_authentication()
예제 #7
0
    def new_session(self):
        self.logged_in = False

        ## Legacy ##
        userdata.delete('pswd')
        userdata.delete('access_token')
        ############

        self._session = Session(HEADERS, base_url=API_URL)
        self._set_authentication()
예제 #8
0
    def new_session(self):
        self.logged_in = False

        host = settings.get('business_host') if settings.getBool(
            'business_account', False) else DEFAULT_HOST
        if host != userdata.get('host', DEFAULT_HOST):
            userdata.delete('access_token')
            userdata.set('host', host)

        self._session = Session(HEADERS, base_url=API_URL.format(host))
        self._set_authentication()
예제 #9
0
class API(object):
    def __init__(self):
        self._session = Session(HEADERS, base_url=API_URL)

    @mem_cache.cached(60 * 10)
    def _shows(self):
        return self._session.get('shows').json()

    def shows(self):
        return self._shows()['shows']

    def show(self, id):
        return self._session.get('shows/{}'.format(id)).json()['show']

    def channels(self):
        return self._shows()['channels']

    def live(self):
        return self._session.get('live-epg').json()['channels']

    def genres(self):
        genres = self.channels()
        genres.extend(self._shows()['genres'])
        return genres

    def genre(self, genre):
        shows = []

        for show in self.shows():
            if genre in show['genres'] or genre == show['channel']:
                shows.append(show)

        return shows

    def search(self, query):
        shows = []

        for show in self.shows():
            if query.lower() in show['name'].lower() or SequenceMatcher(
                    None, query.lower(),
                    show['name'].lower()).ratio() >= SEARCH_MATCH_RATIO:
                shows.append(show)

        return shows

    def get_brightcove_src(self, referenceID):
        brightcove_url = BRIGHTCOVE_URL.format(BRIGHTCOVE_ACCOUNT, referenceID)

        resp = self._session.get(brightcove_url,
                                 headers={'BCOV-POLICY': BRIGHTCOVE_KEY})
        data = resp.json()

        return util.process_brightcove(data)
예제 #10
0
    def new_session(self):
        self._session = Session(HEADERS)
        self._cache_key = self._region = settings.getEnum('region', REGIONS, default=US)

        if self._region in X_FORWARDS:
            self._session.headers.update({'x-forwarded-for': X_FORWARDS[self._region]})

        elif self._region == CUSTOM:
            region_ip = settings.get('region_ip', '0.0.0.0')
            if region_ip != '0.0.0.0':
                self._session.headers.update({'x-forwarded-for': region_ip})
                self._cache_key = region_ip

        self._cache_key += str(settings.getBool('show_epg', False))
예제 #11
0
    def play(self, slug):
        self._refresh_token()
        
        data = self._session.get('/video/{slug}/stream/'.format(slug=slug)).json()
        resp = self._session.head(data['iframe'])
        url = resp.headers.get('Location').replace('.html', '')

        data = Session(headers=HEADERS).get(url).json()
        if 'response' not in data:
            raise APIError('{}'.format(data.get('message', 'unknown error getting playdata')))

        play_url = data['response']['body']['outputs'][0]['url']
        subtitles = data['response']['body'].get('subtitles', [])

        return play_url, subtitles
예제 #12
0
def get_integrations():
    try:
        return Session().gz_json(INTEGRATIONS_URL)
    except Exception as e:
        log.debug('Failed to get integrations')
        log.exception(e)
        return {}
예제 #13
0
class API(object):
    def new_session(self):
        self._session = Session(HEADERS)

    @cached(60 * 10)
    def all_stations(self):
        return self._session.gz_json(STATIONS_URL)
예제 #14
0
    def _process_source(self, source, method_name, file_path):
        remove_file(file_path)

        path = source.path.strip()
        source_type = source.source_type
        archive_type = source.archive_type

        if source_type == Source.TYPE_ADDON:
            addon_id = path
            addon, data = merge_info(addon_id, self.integrations, merging=True)

            if method_name not in data:
                raise Error('{} could not be found for {}'.format(
                    method_name, addon_id))

            template_tags = {
                '$ID': addon_id,
                '$FILE': file_path,
                '$IP': xbmc.getIPAddress(),
            }

            path = data[method_name]
            for tag in template_tags:
                path = path.replace(tag, template_tags[tag])

            path = path.strip()
            if path.lower().startswith('plugin'):
                self._call_addon_method(path)
                return

            if path.lower().startswith('http'):
                source_type = Source.TYPE_URL
            else:
                source_type = Source.TYPE_FILE

            archive_extensions = {
                '.gz': Source.ARCHIVE_GZIP,
                '.xz': Source.ARCHIVE_XZ,
            }

            name, ext = os.path.splitext(path.lower())
            archive_type = archive_extensions.get(ext, Source.ARCHIVE_NONE)

        if source_type == Source.TYPE_URL and path.lower().startswith('http'):
            log.debug('Downloading: {} > {}'.format(path, file_path))
            Session().chunked_dl(path, file_path)
        elif not xbmcvfs.exists(path):
            raise Error(_(_.LOCAL_PATH_MISSING, path=path))
        else:
            log.debug('Copying local file: {} > {}'.format(path, file_path))
            xbmcvfs.copy(path, file_path)

        if archive_type == Source.ARCHIVE_GZIP:
            gzip_extract(file_path)
        elif archive_type == Source.ARCHIVE_XZ:
            xz_extract(file_path)
예제 #15
0
    def get_brightcove_src(self, bc_accont, referenceID):
        headers = {
            'User-Agent':
            'Mozilla/5.0 (CrKey armv7l 1.5.16041) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.0 Safari/537.36',
            'Origin': 'https://www.supercars.com',
            'X-Forwarded-For': '18.233.21.73',
            'BCOV-POLICY': BRIGHTCOVE_KEY,
        }

        brightcove_url = BRIGHTCOVE_URL.format(bc_accont, referenceID)
        data = Session().get(brightcove_url, headers=headers).json()
        return util.process_brightcove(data)
예제 #16
0
    def login(self, username, password):
        self.logout()

        s = Session()
        s.headers.update(HEADERS)

        if not password:
            raise APIError(_.LOGIN_ERROR)

        r = s.get(BASE_URL + 'superview/', timeout=20)
        soup = BeautifulSoup(r.text, 'html.parser')

        login_form = soup.find(id="membersignin")
        inputs = login_form.find_all('input')

        data = {}
        for elem in inputs:
            if elem.attrs.get('value'):
                data[elem.attrs['name']] = elem.attrs['value']

        data.update({
            'signinusername': username,
            'signinpassword': password,
        })

        r = s.post(BASE_URL + 'superview/',
                   data=data,
                   allow_redirects=False,
                   timeout=20)
        if r.status_code != 302:
            raise APIError(_.LOGIN_ERROR)

        if settings.getBool('save_password', False):
            userdata.set(PASSWORD_KEY, password)

        for cookie in r.cookies:
            if cookie.name.startswith('wordpress_logged_in'):
                userdata.set('_cookies', {cookie.name: cookie.value})
                break
예제 #17
0
def _check_news():
    _time = int(time())
    if _time < settings.getInt('_last_news_check', 0) + NEWS_CHECK_TIME:
        return

    settings.setInt('_last_news_check', _time)

    news = Session(timeout=15).gz_json(NEWS_URL)
    if not news:
        return

    if 'id' not in news or news['id'] == settings.get('_last_news_id'):
        return

    settings.set('_last_news_id', news['id'])
    settings.set('_news', json.dumps(news))
예제 #18
0
    def _get(self, url, attempt=1):
        cookies = {'cookie_notice_accepted': 'true'}
        cookies.update(userdata.get('_cookies'))

        r = Session().get(BASE_URL + url,
                          timeout=20,
                          cookies=cookies,
                          headers=HEADERS)

        password = userdata.get(PASSWORD_KEY)
        if 'membersignin' in r.text and password and attempt <= 3:
            self.login(userdata.get('username'), password)
            return self._get(url, attempt=attempt + 1)

        if 'membersignin' in r.text:
            raise APIError(_.SESSION_EXPIRED)

        return r
예제 #19
0
def _avatar(profile, download=False):
    _type = profile.get('avatarImageType')

    if _type == 'user-upload':
        url = api.url('gateway', UPLOAD_AVATAR.format(image_id=profile['avatarImageId'], token=userdata.get('access_token')))
    elif _type == 'character':
        url = api.url('artist', CHARACTER_AVATAR.format(image_id=profile['avatarImageId']))
    else:
        return None

    if not download:
        return url

    dst_path = os.path.join(ADDON_PROFILE, 'profile.png')

    try:
        Session().chunked_dl(url, dst_path)
    except:
        return None
    else:
        return dst_path
예제 #20
0
def check_updates(force=False):
    _time = int(time())
    if not force and _time < settings.getInt('_last_updates_check',
                                             0) + UPDATES_CHECK_TIME:
        return

    settings.setInt('_last_updates_check', _time)

    new_md5 = Session(timeout=15).get(ADDONS_MD5).text.split(' ')[0]
    if not force and new_md5 == settings.get('addon_md5'):
        return 0

    settings.set('_addon_md5', new_md5)

    updates = []
    slyguy_addons = get_slyguy_addons()
    slyguy_installed = [
        x['addonid'] for x in kodi_rpc('Addons.GetAddons', {
            'installed': True,
            'enabled': True
        })['addons'] if x['addonid'] in slyguy_addons
    ]

    for addon_id in slyguy_installed:
        addon = get_addon(addon_id, install=False)
        if not addon:
            continue

        cur_version = addon.getAddonInfo('version')
        new_version = slyguy_addons[addon_id]['version']

        if LooseVersion(cur_version) < LooseVersion(new_version):
            updates.append([addon, cur_version, new_version])

    if not force and not updates:
        return 0

    log.debug('Updating repos due to {} addon updates'.format(len(updates)))
    xbmc.executebuiltin('UpdateAddonRepos')
    return updates
class API(object):
    def new_session(self):
        self.logged_in = False
        self._session = Session(HEADERS, timeout=30)
        self._set_authentication(userdata.get('access_token'))
        self._set_languages()

    @mem_cache.cached(60 * 60, key='config')
    def get_config(self):
        return self._session.get(CONFIG_URL).json()

    def _set_languages(self):
        self._app_language = 'en'
        self._playback_language = 'en'
        self._subtitle_language = 'en'
        self._kids_mode = False
        self._maturity_rating = 9999
        self._region = None

        if not self.logged_in:
            return

        token = userdata.get('access_token')
        if '..' in token:  #JWE Token
            return

        data = jwt_data(token)['context']

        #   self._maturity_rating = data['preferred_maturity_rating']['implied_maturity_rating']
        #   self._region = data['location']['country_code']

        for profile in data['profiles']:
            if profile['id'] == data['active_profile_id']:
                self._app_language = profile['language_preferences'][
                    'app_language']
                self._playback_language = profile['language_preferences'][
                    'playback_language']
                self._subtitle_language = profile['language_preferences'][
                    'subtitle_language']
                self._kids_mode = profile['kids_mode_enabled']
                return

    @mem_cache.cached(60 * 60, key='transaction_id')
    def _transaction_id(self):
        return str(uuid.uuid4())

    @property
    def session(self):
        return self._session

    def _set_authentication(self, access_token):
        if not access_token:
            return

        ## JWT requires Bearer
        if '..' not in access_token:
            access_token = 'Bearer {}'.format(access_token)

        self._session.headers.update({'Authorization': access_token})
        self._session.headers.update(
            {'x-bamsdk-transaction-id': self._transaction_id()})
        self.logged_in = True

    def _refresh_token(self, force=False):
        if not force and userdata.get('expires', 0) > time():
            return

        payload = {
            'refresh_token': userdata.get('refresh_token'),
            'grant_type': 'refresh_token',
            'platform': 'android',
        }

        self._oauth_token(payload)

    def _oauth_token(self, payload):
        headers = {
            'Authorization': 'Bearer {}'.format(API_KEY),
        }

        endpoint = self.get_config(
        )['services']['token']['client']['endpoints']['exchange']['href']
        token_data = self._session.post(endpoint,
                                        data=payload,
                                        headers=headers).json()

        self._check_errors(token_data)

        self._set_authentication(token_data['access_token'])

        userdata.set('access_token', token_data['access_token'])
        userdata.set('expires', int(time() + token_data['expires_in'] - 15))

        if 'refresh_token' in token_data:
            userdata.set('refresh_token', token_data['refresh_token'])

    def login(self, username, password):
        self.logout()

        try:
            self._do_login(username, password)
        except:
            self.logout()
            raise

    def _check_errors(self, data, error=_.API_ERROR):
        if not type(data) is dict:
            return

        if data.get('errors'):
            error_msg = ERROR_MAP.get(
                data['errors'][0].get('code')) or data['errors'][0].get(
                    'description') or data['errors'][0].get('code')
            raise APIError(_(error, msg=error_msg))

        elif data.get('error'):
            error_msg = ERROR_MAP.get(data.get('error_code')) or data.get(
                'error_description') or data.get('error_code')
            raise APIError(_(error, msg=error_msg))

        elif data.get('status') == 400:
            raise APIError(_(error, msg=data.get('message')))

    def _do_login(self, username, password):
        headers = {
            'Authorization': 'Bearer {}'.format(API_KEY),
        }

        payload = {
            'deviceFamily': 'android',
            'applicationRuntime': 'android',
            'deviceProfile': 'tv',
            'attributes': {},
        }

        endpoint = self.get_config()['services']['device']['client'][
            'endpoints']['createDeviceGrant']['href']
        device_data = self._session.post(endpoint,
                                         json=payload,
                                         headers=headers,
                                         timeout=20).json()

        self._check_errors(device_data)

        payload = {
            'subject_token': device_data['assertion'],
            'subject_token_type': 'urn:bamtech:params:oauth:token-type:device',
            'platform': 'android',
            'grant_type': 'urn:ietf:params:oauth:grant-type:token-exchange',
        }

        self._oauth_token(payload)

        payload = {
            'email': username,
            'password': password,
        }

        endpoint = self.get_config()['services']['bamIdentity']['client'][
            'endpoints']['identityLogin']['href']
        login_data = self._session.post(endpoint, json=payload).json()

        self._check_errors(login_data)

        endpoint = self.get_config()['services']['account']['client'][
            'endpoints']['createAccountGrant']['href']
        grant_data = self._session.post(endpoint,
                                        json={
                                            'id_token': login_data['id_token']
                                        }).json()

        payload = {
            'subject_token': grant_data['assertion'],
            'subject_token_type':
            'urn:bamtech:params:oauth:token-type:account',
            'platform': 'android',
            'grant_type': 'urn:ietf:params:oauth:grant-type:token-exchange',
        }

        self._oauth_token(payload)

    def _json_call(self, endpoint, variables=None):
        self._refresh_token()
        params = {'variables': json.dumps(variables)} if variables else None
        data = self._session.get(endpoint, params=params).json()
        self._check_errors(data)
        return data

    def profiles(self):
        self._refresh_token(force=True)
        endpoint = self.get_config()['services']['account']['client'][
            'endpoints']['getUserProfiles']['href']
        return self._json_call(endpoint)

    def active_profile(self):
        endpoint = self.get_config()['services']['account']['client'][
            'endpoints']['getActiveUserProfile']['href']
        return self._json_call(endpoint)

    def set_profile(self, profile, pin=None):
        self._refresh_token()

        endpoint = self.get_config()['services']['account']['client'][
            'endpoints']['setActiveUserProfile']['href'].format(
                profileId=profile['profileId'])

        payload = {}
        if pin:
            payload['entryPin'] = str(pin)

        grant_data = self._session.put(endpoint, json=payload).json()
        self._check_errors(grant_data)

        payload = {
            'subject_token': grant_data['assertion'],
            'subject_token_type':
            'urn:bamtech:params:oauth:token-type:account',
            'platform': 'android',
            'grant_type': 'urn:ietf:params:oauth:grant-type:token-exchange',
        }

        self._oauth_token(payload)

        userdata.set(
            'profile_language',
            profile['attributes']['languagePreferences']['appLanguage'])

    def search(self, query, page=1, page_size=PAGE_SIZE):
        variables = {
            'preferredLanguage': [self._app_language],
            'index': 'disney_global',
            'q': query,
            'page': page,
            'pageSize': page_size,
            'contentTransactionId': self._transaction_id(),
        }

        endpoint = self.get_config()['services']['content']['client'][
            'endpoints']['searchPersisted']['href'].format(
                queryId='core/disneysearch')
        return self._json_call(endpoint, variables)['data']['disneysearch']

    def avatar_by_id(self, ids):
        variables = {
            'preferredLanguage': [self._app_language],
            'avatarId': ids,
        }

        endpoint = self.get_config()['services']['content']['client'][
            'endpoints']['searchPersisted']['href'].format(
                queryId='core/AvatarByAvatarId')
        return self._json_call(endpoint, variables)['data']['AvatarByAvatarId']

    def video_bundle(self, family_id):
        variables = {
            'preferredLanguage': [self._app_language],
            'familyId': family_id,
            'contentTransactionId': self._transaction_id(),
        }

        endpoint = self.get_config()['services']['content']['client'][
            'endpoints']['dmcVideos']['href'].format(
                queryId='core/DmcVideoBundle')
        return self._json_call(endpoint, variables)['data']['DmcVideoBundle']

    def extras(self, family_id):
        variables = {
            'preferredLanguage': [self._app_language],
            'familyId': family_id,
            'page': 1,
            'pageSize': 999,
            'contentTransactionId': self._transaction_id(),
        }

        endpoint = self.get_config()['services']['content']['client'][
            'endpoints']['dmcVideos']['href'].format(queryId='core/DmcExtras')
        return self._json_call(endpoint, variables)['data']['DmcExtras']

    def series_bundle(self, series_id, page=1, page_size=PAGE_SIZE):
        variables = {
            'preferredLanguage': [self._app_language],
            'seriesId': series_id,
            'episodePage': page,
            'episodePageSize': page_size,
            'contentTransactionId': self._transaction_id(),
        }

        endpoint = self.get_config()['services']['content']['client'][
            'endpoints']['dmcVideos']['href'].format(
                queryId='core/DmcSeriesBundle')
        return self._json_call(endpoint, variables)['data']['DmcSeriesBundle']

    def episodes(self, season_ids, page=1, page_size=PAGE_SIZE_EPISODES):
        variables = {
            'preferredLanguage': [self._app_language],
            'seasonId': season_ids,
            'episodePage': page,
            'episodePageSize': page_size,
            'contentTransactionId': self._transaction_id(),
        }

        endpoint = self.get_config()['services']['content']['client'][
            'endpoints']['dmcVideos']['href'].format(
                queryId='core/DmcEpisodes')
        return self._json_call(endpoint, variables)['data']['DmcEpisodes']

    def collection_by_slug(self, slug, content_class):
        variables = {
            'preferredLanguage': [self._app_language],
            'contentClass': content_class,
            'slug': slug,
            'contentTransactionId': self._transaction_id(),
        }

        #endpoint = self.get_config()['services']['content']['client']['endpoints']['dmcVideos']['href'].format(queryId='disney/CollectionBySlug')
        endpoint = self.get_config()['services']['content']['client'][
            'endpoints']['dmcVideos']['href'].format(
                queryId='core/CompleteCollectionBySlug')
        return self._json_call(endpoint,
                               variables)['data']['CompleteCollectionBySlug']

    def set_by_id(self, set_id, set_type, page=1, page_size=PAGE_SIZE):
        variables = {
            'preferredLanguage': [self._app_language],
            'setId': set_id,
            'setType': set_type,
            'page': page,
            'pageSize': page_size,
            'contentTransactionId': self._transaction_id(),
        }

        #endpoint = self.get_config()['services']['content']['client']['endpoints']['dmcVideos']['href'].format(queryId='disney/SetBySetId')
        endpoint = self.get_config()['services']['content']['client'][
            'endpoints']['dmcVideos']['href'].format(queryId='core/SetBySetId')
        return self._json_call(endpoint, variables)['data']['SetBySetId']

    def add_watchlist(self, content_id):
        variables = {
            'preferredLanguage': [self._app_language],
            'contentIds': content_id,
        }

        endpoint = self.get_config()['services']['content']['client'][
            'endpoints']['dmcVideos']['href'].format(
                queryId='core/AddToWatchlist')
        return self._json_call(endpoint, variables)['data']['AddToWatchlist']

    def delete_watchlist(self, content_id):
        variables = {
            'preferredLanguage': [self._app_language],
            'contentIds': content_id,
        }

        endpoint = self.get_config()['services']['content']['client'][
            'endpoints']['dmcVideos']['href'].format(
                queryId='core/DeleteFromWatchlist')
        data = self._json_call(endpoint,
                               variables)['data']['DeleteFromWatchlist']
        xbmc.sleep(500)
        return data

    def up_next(self, content_id):
        variables = {
            'preferredLanguage': [self._app_language],
            'contentId': content_id,
            'contentTransactionId': self._transaction_id(),
        }

        endpoint = self.get_config()['services']['content']['client'][
            'endpoints']['dmcVideos']['href'].format(queryId='core/UpNext')
        return self._json_call(endpoint, variables)['data']['UpNext']

    def videos(self, content_id):
        variables = {
            'preferredLanguage': [self._app_language],
            'contentId': content_id,
            'contentTransactionId': self._transaction_id(),
        }

        endpoint = self.get_config()['services']['content']['client'][
            'endpoints']['dmcVideos']['href'].format(queryId='core/DmcVideos')
        return self._json_call(endpoint, variables)['data']['DmcVideos']

    def update_resume(self, media_id, fguid, playback_time):
        payload = [{
            "server": {
                "fguid": fguid,
                "mediaId": media_id,
            },
            "client": {
                "event": "urn:dss:telemetry-service:event:stream-sample",
                "timestamp": str(int(time() * 1000)),
                "play_head": playback_time,
                # "playback_session_id": str(uuid.uuid4()),
                # "interaction_id": str(uuid.uuid4()),
                # "bitrate": 4206,
            },
        }]

        self._refresh_token()
        endpoint = self.get_config(
        )['services']['telemetry']['client']['endpoints']['postEvent']['href']
        return self._session.post(endpoint, json=payload).status_code

    def playback_data(self, playback_url):
        self._refresh_token(force=True)

        config = self.get_config()
        scenario = config['services']['media']['extras'][
            'restrictedPlaybackScenario']

        if settings.getBool('wv_secure', False):
            scenario = config['services']['media']['extras'][
                'playbackScenarioDefault']

            if settings.getBool('h265', False):
                scenario += '-h265'

                if settings.getBool('dolby_vision', False):
                    scenario += '-dovi'
                elif settings.getBool('hdr10', False):
                    scenario += '-hdr10'

                if settings.getBool('dolby_atmos', False):
                    scenario += '-atmos'

        headers = {
            'accept': 'application/vnd.media-service+json; version=4',
            'authorization': userdata.get('access_token')
        }

        endpoint = playback_url.format(scenario=scenario)
        playback_data = self._session.get(endpoint, headers=headers).json()
        self._check_errors(playback_data)

        return playback_data

    def continue_watching(self):
        set_id = CONTINUE_WATCHING_SET_ID
        set_type = CONTINUE_WATCHING_SET_TYPE
        data = self.set_by_id(set_id, set_type, page_size=999)

        continue_watching = {}
        for row in data['items']:
            if row['meta']['bookmarkData']:
                play_from = row['meta']['bookmarkData']['playhead']
            else:
                play_from = 0

            continue_watching[row['contentId']] = play_from

        return continue_watching

    def logout(self):
        userdata.delete('access_token')
        userdata.delete('expires')
        userdata.delete('refresh_token')

        mem_cache.delete('transaction_id')
        mem_cache.delete('config')

        self.new_session()
예제 #22
0
 def __init__(self):
     self._session = Session(HEADERS, base_url=API_URL)
예제 #23
0
 def new_session(self):
     self._session = Session(HEADERS)
예제 #24
0
class API(object):
    def new_session(self):
        self.logged_in = False

        host = settings.get('business_host') if settings.getBool(
            'business_account', False) else DEFAULT_HOST
        if host != userdata.get('host', DEFAULT_HOST):
            userdata.delete('access_token')
            userdata.set('host', host)

        self._session = Session(HEADERS, base_url=API_URL.format(host))
        self._set_authentication()

    def _set_authentication(self):
        token = userdata.get('access_token')
        if not token:
            return

        self._session.headers.update(
            {'Authorization': 'Bearer {}'.format(token)})
        self.logged_in = True

    def my_courses(self, page=1, query=None):
        params = {
            'page':
            page,
            'page_size':
            PAGE_SIZE,
            'ordering':
            'title',
            'fields[course]':
            'id,title,image_480x270,image_750x422,headline,num_published_lectures,content_info,completion_ratio',
        }

        if query:
            params['search'] = query

        return self._session.get('users/me/subscribed-courses',
                                 params=params).json()

    def chapters(self, course_id, page=1):
        params = {
            'page': page,
            'page_size': PAGE_SIZE,
            'fields[course]': 'image_480x270',
            'fields[chapter]': 'description,object_index,title,course',
            'fields[lecture]': 'id',
            'fields[practice]': 'id',
            'fields[quiz]': 'id',
        }

        data = self._session.get(
            'courses/{}/cached-subscriber-curriculum-items'.format(course_id),
            params=params).json()
        rows = [r for r in data['results'] if r['_class'] == 'chapter']
        return rows, data['next']

    def lectures(self, course_id, chapter_id, page=1):
        params = {
            'page': page,
            'page_size': PAGE_SIZE,
            'fields[course]': 'image_480x270,title',
            'fields[chapter]': 'id',
            'fields[lecture]':
            'title,object_index,description,is_published,course,id,asset',
            'fields[asset]': 'asset_type,length,status',
            'fields[practice]': 'id',
            'fields[quiz]': 'id',
        }

        data = self._session.get(
            'courses/{}/cached-subscriber-curriculum-items'.format(course_id),
            params=params).json()

        lectures = []
        found = False
        for row in data['results']:
            if not found and row['_class'] == 'chapter' and row['id'] == int(
                    chapter_id):
                found = True

            elif found and row['_class'] == 'lecture' and row[
                    'is_published'] and row['asset']['asset_type'] in (
                        'Video', 'Audio'):
                lectures.append(row)

            elif found and row['_class'] == 'chapter':
                break

        return lectures, data['next']

    def get_stream_data(self, asset_id):
        params = {
            'fields[asset]': '@all',
        }

        data = self._session.get('assets/{0}'.format(asset_id),
                                 params=params).json()
        if 'detail' in data:
            raise APIError(data['detail'])

        return data

    def login(self, username, password):
        data = {
            'email': username,
            'password': password,
            'upow': self._get_upow(username, 'login')
        }

        params = {
            'fields[user]': 'title,image_100x100,name,access_token',
        }

        r = self._session.post('auth/udemy-auth/login/',
                               params=params,
                               data=data)
        try:
            data = r.json()
        except:
            raise APIError(_(_.LOGIN_ERROR, msg=r.status_code))

        access_token = data.get('access_token')
        if not access_token:
            raise APIError(_(_.LOGIN_ERROR, msg=data.get('detail', '')))

        userdata.set('access_token', access_token)
        self._set_authentication()

    def logout(self):
        userdata.delete('access_token')
        self.new_session()

    def _get_upow(self, message, secret):
        date = datetime.datetime.today().strftime('%Y%m%d')

        def get_token(email, date, secret):
            message = email + date
            i = 0

            for x in range(0, 20):
                i3 = i * 50

                while True:
                    i2 = i + 1
                    if i3 >= i2 * 50:
                        break

                    i4 = i3 * 1000
                    i3 += 1
                    token = hash_calc(i4, i3 * 1000, message, secret)
                    if token:
                        return token

                i = i2

            return None

        def m26785a(i):
            f19175e = ""
            while i >= 0:
                f19175e += chr(((i % 26) + 65))
                i = int(i / 26) - 1
            return f19175e[::-1]

        def hash_calc(i, i2, message, password):
            a = m26785a(i)
            _bytes = bytearray(message + a, 'utf8')
            password = password.encode()

            while i < i2:
                _i = i
                if (_i % 26 == 0):
                    _bytes = bytearray(message + m26785a(_i), 'utf8')
                else:
                    _bytes[len(_bytes) - 1] = (_bytes[len(_bytes) - 1] + 1)

                doFinal = hmac.new(password, _bytes,
                                   digestmod=hashlib.sha256).hexdigest()
                if doFinal[0:2] == '00' and doFinal[2:4] == '00':
                    return m26785a(i)

                i += 1

            return None

        return date + get_token(message, date, secret)
예제 #25
0
def _channels():
    return Session().gz_json(DATA_URL)
예제 #26
0
 def new_session(self):
     self.logged_in = False
     self._session = Session(base_url=API_URL, headers=HEADERS)
     self._set_authentication()
예제 #27
0
class API(object):
    def new_session(self):
        self.logged_in = False
        self._session = Session(base_url=API_URL, headers=HEADERS)
        self._set_authentication()

    def _set_authentication(self):
        access_token = userdata.get('access_token')
        if not access_token:
            return

        self._session.headers.update({'authorization': access_token})
        self.logged_in = True

    def _refresh_token(self, force=False):
        refresh_token = userdata.get('refresh_token')
        if not refresh_token or (not force
                                 and userdata.get('expires', 0) > time()):
            return

        params = {
            'key': GOOGLE_KEY,
        }

        payload = {
            'grantType': 'refresh_token',
            'refreshToken': refresh_token,
        }

        data = self._session.post(TOKEN_URL, params=params,
                                  json=payload).json()
        if 'error' in data:
            self.logout()
            raise APIError(data['error']['message'])

        userdata.set('access_token', data['access_token'])
        userdata.set('refresh_token', data['refresh_token'])
        userdata.set('expires', int(time()) + int(data['expires_in']) - 30)
        self._set_authentication()

    def channels(self):
        self._refresh_token()

        params = {
            'noGuideData': True,
        }

        return self._session.get('/programGuide', params=params).json()

    def play(self, id):
        self._refresh_token()

        params = {
            'channelId': id,
        }

        return self._session.get('/playbackAuthenticated',
                                 params=params).json()

    def epg(self, id=None):
        self._refresh_token()

        params = {}
        if id:
            params['channelId'] = id

        return self._session.get('/programGuide', params=params).json()

    def login(self, email, password, register=False):
        self.logout()

        params = {
            'key': GOOGLE_KEY,
        }

        payload = {
            'email': email,
            'password': password,
            'returnSecureToken': True,
        }

        data = self._session.post(REGISTER_URL if register else LOGIN_URL,
                                  params=params,
                                  json=payload).json()
        if 'error' in data:
            raise APIError(data['error']['message'])

        userdata.set('refresh_token', data['refreshToken'])
        self._refresh_token(force=True)

    def logout(self):
        userdata.delete('access_token')
        userdata.delete('refresh_token')
        userdata.delete('expires')
        self.new_session()
 def new_session(self):
     self.logged_in = False
     self._session = Session(HEADERS, timeout=30)
     self._set_authentication(userdata.get('access_token'))
     self._set_languages()
예제 #29
0
class API(object):
    def new_session(self):
        self.logged_in = False

        self._session = Session(HEADERS, base_url=API_URL)

        if userdata.get('singtel_tv_no'):
            self.logged_in = True

    def login(self, singtel_tv_no, identification_no):
        self.logout()

        device_id = hash_6(singtel_tv_no, length=16)

        payload = {
            'deviceType': APP_DEVICE,
            'deviceId': device_id,
            'identityType': APP_ID_TYPE,
            'identityId': identification_no,
            'iptvNo': singtel_tv_no,
            'appId': APP_ID,
            'appKey': APP_KEY,
            'mode': APP_MODE,
            'ver': APP_VER,
        }

        data = self._session.post('/HomeLoginService.aspx',
                                  data={
                                      'JSONtext': json.dumps(payload)
                                  }).json()['item'][0]
        if data.get('StatusCode'):
            raise APIError(_.LOGIN_ERROR)

        userdata.set('device_id', device_id)
        userdata.set('singtel_tv_no', singtel_tv_no)
        userdata.set('identification_no', identification_no)

        return data

    @mem_cache.cached(60 * 5)
    def channels(self):
        data = self._session.gz_json(DATA_URL)
        channels = [
            x for x in data['getAuthorizationResponse']['channelList']
            if x['isLive'].upper() == 'Y'
        ]

        user_data = self.login(userdata.get('singtel_tv_no'),
                               userdata.get('identification_no'))

        if user_data['OTTAccess'].upper() != 'Y':
            guest_ids = [
                int(x['ChannelID']) for x in user_data['guestPreviewChannels']
            ]
            channels = [x for x in channels if x['id'] in guest_ids]
        else:
            channels = [
                x for x in channels
                if x['shortName'] in user_data['SubscribedCallLetters']
            ]

        return channels

    def _stop_stream(self, channel_id, token):
        start = arrow.utcnow()
        end = start.shift(seconds=10)

        payload = {
            'deviceType': APP_DEVICE,
            'deviceId': userdata.get('device_id'),
            'identityType': APP_ID_TYPE,
            'identityId': userdata.get('identification_no'),
            'iptvNo': userdata.get('singtel_tv_no'),
            'channelID': channel_id,
            'startTime': start.format('YYYY-MM-DD HH:mm:ss'),
            'stopTime': end.format('YYYY-MM-DD HH:mm:ss'),
            'bitRates': '1',
            'token': token,
            'appId': APP_ID,
            'appKey': APP_KEY,
        }

        resp = self._session.post('/LogStopStream.aspx',
                                  data={'JSONtext': json.dumps(payload)})

        return resp.ok

    def play(self, channel_id, call_letter):
        payload = {
            'deviceType': APP_DEVICE,
            'deviceId': userdata.get('device_id'),
            'identityType': APP_ID_TYPE,
            'identityId': userdata.get('identification_no'),
            'iptvNo': userdata.get('singtel_tv_no'),
            'callLetter': call_letter,
            'channelID': channel_id,
            'appId': APP_ID,
            'appKey': APP_KEY,
            'mode': APP_MODE,
            'ver': APP_VER,
        }

        data = self._session.get('/WatchOTTStreaming.aspx',
                                 data={
                                     'JSONtext': json.dumps(payload)
                                 }).json()['item'][0]
        if data.get('StatusCode'):
            raise APIError(_(_.PLAYBACK_ERROR, error=data.get('StatusDesc')))

        self._stop_stream(channel_id, data['UserToken'])

        return data

    def logout(self):
        userdata.delete('singtel_tv_no')
        userdata.delete('identification_no')
        userdata.delete('device_id')
        mem_cache.empty()
        self.new_session()
예제 #30
0
from distutils.version import LooseVersion

from kodi_six import xbmc

from slyguy import gui, router, settings
from slyguy.session import Session
from slyguy.util import kodi_rpc, get_addon
from slyguy.log import log
from slyguy.constants import ROUTE_SERVICE, ROUTE_SERVICE_INTERVAL, KODI_VERSION

from .proxy import Proxy
from .monitor import monitor
from .player import Player
from .constants import *

session = Session(timeout=15)


def _check_updates():
    _time = int(time())
    if _time < settings.getInt('_last_updates_check', 0) + UPDATES_CHECK_TIME:
        return

    settings.setInt('_last_updates_check', _time)

    new_md5 = session.get(ADDONS_MD5).text.split(' ')[0]
    if new_md5 == settings.get('addon_md5'):
        return

    settings.set('_addon_md5', new_md5)