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)))
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
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 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)))
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')
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()
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()
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()
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)
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))
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
def get_integrations(): try: return Session().gz_json(INTEGRATIONS_URL) except Exception as e: log.debug('Failed to get integrations') log.exception(e) return {}
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)
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)
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)
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
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))
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
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
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()
def __init__(self): self._session = Session(HEADERS, base_url=API_URL)
def new_session(self): self._session = Session(HEADERS)
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)
def _channels(): return Session().gz_json(DATA_URL)
def new_session(self): self.logged_in = False self._session = Session(base_url=API_URL, headers=HEADERS) self._set_authentication()
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()
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()
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)