def new_session(self): self.logged_in = False self._session = Session(HEADERS) self._set_authentication() settings.setBool('_logged_in', self.logged_in)
def process(item, item_type): if item.path_type == Source.TYPE_ADDON: _opath = sys.path[:] _ocwd = os.getcwd() try: addons_path = xbmc.translatePath('special://home/addons').decode( "utf-8") addon_path = os.path.join(addons_path, item.path) os.chdir(addon_path) sys.path.insert(0, addon_path) os.environ['ADDON_ID'] = item.path f, filename, description = imp.find_module(item.path, [addons_path]) package = imp.load_module(item.path, f, filename, description) f, filename, description = imp.find_module(MERGE_MODULE, package.__path__) try: module = imp.load_module( '{}.{}'.format(item.path, MERGE_MODULE), f, filename, description) if item_type == Source.PLAYLIST: method = getattr(module, METHOD_PLAYLIST) elif item_type == Source.EPG: method = getattr(module, METHOD_EPG) return method() finally: f.close() finally: sys.path = _opath os.chdir(_ocwd) os.environ.pop('ADDON_ID', None) for m in sys.modules.keys(): if m.startswith(item.path): del (sys.modules[m]) elif item.path_type == Source.TYPE_REMOTE: r = Session().get(item.path, stream=True) r.raise_for_status() in_file = StringIO.StringIO(r.content) elif item.path_type == Source.TYPE_LOCAL: in_file = open(xbmc.translatePath(item.path)) if item.file_type == Source.FILE_GZIP: in_file = gzip.GzipFile(fileobj=in_file) return in_file.read()
def dns4me_login(**kwargs): username = gui.input('dns4me Username').strip() if not username: return password = gui.input('dns4me Password', hide_input=True).strip() if not password: return data = Session().post('https://dns4me.net/api/v2/get_apikey', data={ 'username': username, 'password': password }).json() if 'apikey' in data: userdata.set('dns4me_key', data['apikey']) else: plugin.exception('Failed to login') gui.refresh()
def process_file(item, method_name, file_path): if item.path_type == Source.TYPE_ADDON: addon = xbmcaddon.Addon(item.path) addon_id = addon.getAddonInfo('id') addon_path = xbmc.translatePath(addon.getAddonInfo('path')) merge_path = os.path.join(addon_path, MERGE_SETTING_FILE) with open(merge_path) as f: data = json.load(f) item.path = data[method_name].replace('$ID', addon_id).replace( '$FILE', file_path) if item.path.lower().startswith('plugin'): call_addon_method(item.path) return if item.path.lower().startswith('http'): item.path_type = Source.TYPE_REMOTE else: item.path_type = Source.TYPE_LOCAL if item.path.lower().endswith('.gz'): item.file_type = Source.FILE_GZIP if item.path_type == Source.TYPE_REMOTE: log.debug('Downloading: {} > {}'.format(item.path, file_path)) Session().chunked_dl(item.path, file_path) elif item.path_type == Source.TYPE_LOCAL: path = xbmc.translatePath(item.path) if not os.path.exists(path): raise Error(_(_.LOCAL_PATH_MISSING, path=path)) log.debug('Copying local file: {} > {}'.format(path, file_path)) shutil.copyfile(path, file_path) if item.file_type == Source.FILE_GZIP: gzip_extract(file_path)
class API(object): def new_session(self): self.logged_in = False self._session = Session(HEADERS) self._set_authentication() def _set_authentication(self): token = userdata.get('access_token') if not token: return self._session.headers.update({'sky-x-access-token': token}) self.logged_in = True def series(self, id): return self._session.get(CONTENT_URL + id).json() def content(self, section='', sortby='TITLE', text='', title=None, channels='', start=0): params = { 'title': title or '', 'genre': '', 'rating': '', 'text': text, 'sortBy': sortby, 'lastChance': 'true' if sortby == 'LASTCHANCE' else 'false', 'type': '', 'channel': channels, 'section': section, 'size': 100, 'start': start, } return self._session.get(CONTENT_URL, params=params).json() def channels(self): data = self._session.get(CHANNELS_URL).json() return data['entries'] def login(self, username, password): device_id = hashlib.md5(username).hexdigest() data = { "deviceDetails": "test", "deviceID": device_id, "deviceIP": DEVICE_IP, "password": password, "username": username } resp = self._session.post(AUTH_URL, json=data) data = resp.json() if resp.status_code != 200 or 'sessiontoken' not in data: raise APIError(_(_.LOGIN_ERROR, message=data.get('message'))) userdata.set('access_token', data['sessiontoken']) userdata.set('device_id', device_id) if settings.getBool('save_password', False): userdata.set('pswd', password) self._set_authentication() data = self._session.get(SUBSCRIPTIONS_URL.format(data['profileId'])).json() userdata.set('subscriptions', data['onlineSubscriptions']) def _renew_token(self): password = userdata.get('pswd') if password: self.login(userdata.get('username'), password) return data = { "deviceID": userdata.get('device_id'), "deviceIP": DEVICE_IP, "sessionToken": userdata.get('access_token'), } resp = self._session.post(RENEW_URL, json=data) data = resp.json() if resp.status_code != 200 or 'sessiontoken' not in data: raise APIError(_(_.RENEW_TOKEN_ERROR, message=data.get('message'))) userdata.set('access_token', data['sessiontoken']) self._set_authentication() def _get_play_token(self): self._renew_token() params = { 'profileId': userdata.get('device_id'), 'deviceId': userdata.get('device_id'), 'partnerId': 'skygo', 'description': 'ANDROID', } resp = self._session.get(TOKEN_URL, params=params) data = resp.json() if resp.status_code != 200 or 'token' not in data: raise APIError(_(_.TOKEN_ERROR, message=data.get('message'))) return data['token'] def play_media(self, id): token = self._get_play_token() params = { 'form': 'json', 'types': None, 'fields': 'id,content', 'byId': id, } data = self._session.get(PLAY_URL, params=params).json() videos = data['entries'][0]['media$content'] chosen = videos[0] for video in videos: if video['plfile$format'] == 'MPEG-DASH': chosen = video break url = '{}&auth={}&formats=mpeg-dash&tracking=true'.format(chosen['plfile$url'], token) pid = chosen['plfile$url'].split('?')[0].split('/')[-1] license = WIDEVINE_URL.format(token=token, pid=pid, challenge='B{SSM}') url = self._get_location(url) return url, license def _get_location(self, url): resp = self._session.get(url, allow_redirects=False) if resp.status_code != 302: data = resp.json() raise APIError(_(_.PLAY_ERROR, message=data.get('description'))) url = resp.headers.get('location') if 'faxs' in url: raise APIError(_.ADOBE_ERROR) return url def play_channel(self, id): token = self._get_play_token() url = PLAY_CHANNEL_URL.format(id=id, auth=token) url = self._get_location(url) return url def epg(self, ids, start=None, end=None): start = start or arrow.utcnow() end = end or start.shift(days=1) params = { 'startTimestamp': '{}000'.format(start.timestamp), 'endTimestamp': '{}000'.format(end.timestamp), 'channelIds': ','.join(ids), } return self._session.get(EPG_URL, params=params).json()['events'] def logout(self): userdata.delete('device_id') userdata.delete('access_token') userdata.delete('pswd') userdata.delete('subscriptions') self.new_session()
def playlist(output, **kwargs): Session().chunked_dl(PLAYLIST_URL, output)
class API(object): def new_session(self): self.logged_in = False self._session = Session(HEADERS) self._set_authentication() def _set_authentication(self): access_token = userdata.get('access_token') if not access_token: return self._session.headers.update( {'authorization': 'Bearer {}'.format(access_token)}) self.logged_in = True def _oauth_token(self, data): token_data = self._session.post( 'https://auth.kayosports.com.au/oauth/token', json=data).json() if 'error' in token_data: raise APIError( _(_.LOGIN_ERROR, msg=token_data.get('error_description'))) account_status = None try: b64_string = token_data['access_token'].split('.')[1] b64_string += "=" * ((4 - len(b64_string) % 4) % 4) #fix padding data = json.loads(b64decode(b64_string)) account_status = data['https://kayosports.com.au/status'][ 'account_status'] except: log.debug('Failed to get account status') if account_status and account_status != 'ACTIVE_SUBSCRIPTION': raise APIError(_.INVALID_SUBSCRIPTION) 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']) self._set_authentication() def _refresh_token(self): if userdata.get('expires', 0) > time(): return payload = { "refresh_token": userdata.get('refresh_token'), "grant_type": "refresh_token", "client_id": CLIENTID, } self._oauth_token(payload) def login(self, username, password): payload = { "audience": "kayosports.com.au", "grant_type": "http://auth0.com/oauth/grant-type/password-realm", "scope": "openid offline_access", "realm": "prod-martian-database", "client_id": CLIENTID, "username": username, "password": password, } self._oauth_token(payload) def profiles(self): self._refresh_token() return self._session.get( 'https://profileapi.kayosports.com.au/user/profile').json() def sport_menu(self): return self._session.get( 'https://resources.kayosports.com.au/production/sport-menu/lists/default.json' ).json() def cdn_selection(self, media_type): return self._session.get( 'https://cdnselectionserviceapi.kayosports.com.au/android/usecdn/mobile/{}' .format(media_type)).json().get('useCDN') #landing has heros and panels def landing(self, name, **kwargs): params = { 'evaluate': 99, 'resourcesEnv': 'production', 'chromecastEnv': 'production', 'statsEnv': 'production', } params.update(**kwargs) return self._session.get( 'https://vccapi.kayosports.com.au/content/types/landing/names/{}'. format(name), params=params).json() #panel has shows and episodes def panel(self, id, **kwargs): params = { 'evaluate': 3, } params.update(**kwargs) return self._session.get( 'https://vccapi.kayosports.com.au/content/types/carousel/keys/{}'. format(id), params=params).json()[0] #show has episodes and panels def show(self, show_id, season_id=None, **kwargs): params = { 'evaluate': 3, 'showCategory': show_id, 'seasonCategory': season_id, } params.update(**kwargs) return self._session.get( 'https://vccapi.kayosports.com.au/content/types/landing/names/show', params=params).json() def event(self, id, **kwargs): params = { 'evaluate': 3, 'event': id, } params.update(**kwargs) return self._session.get( 'https://vccapi.kayosports.com.au/content/types/landing/names/event', params=params).json()[0]['contents'][0]['data']['asset'] def stream(self, asset): self._refresh_token() params = { 'fields': 'alternativeStreams', } data = self._session.post( 'https://vmndplay.kayosports.com.au/api/v1/asset/{}/play'.format( asset), params=params, json={}).json() if 'errors' in data: raise APIError(_(_.ASSET_ERROR, msg=data['errors'][0]['detail'])) return data['data'][0] def logout(self): userdata.delete('access_token') userdata.delete('refresh_token') userdata.delete('expires') userdata.delete('profile') self.new_session()
def epg(output, **kwargs): Session().chunked_dl(EPG_URL.format(region=get_region()), output)
def get_channels(region): return Session().get(M3U8_URL.format(region=region)).json()
def new_session(self): self.logged_in = False self._session = Session(HEADERS, base_url=API_URL) self._set_authentication()
class API(object): def new_session(self): self.logged_in = False self._session = Session(HEADERS) self._set_authentication() def _set_authentication(self): access_token = userdata.get('access_token') if not access_token: return self._session.headers.update({'authorization': 'Bearer {}'.format(access_token)}) self.logged_in = True def _oauth_token(self, data): token_data = self._session.post('https://auth.kayosports.com.au/oauth/token', json=data).json() if 'error' in token_data: raise APIError(_(_.LOGIN_ERROR, msg=token_data.get('error_description'))) 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']) self._set_authentication() def _refresh_token(self): if userdata.get('expires', 0) > time(): return payload = { "refresh_token": userdata.get('refresh_token'), "grant_type": "refresh_token", "client_id": CLIENTID, } self._oauth_token(payload) def login(self, username, password): payload = { "audience": "kayosports.com.au", "grant_type": "http://auth0.com/oauth/grant-type/password-realm", "scope": "openid offline_access", "realm": "prod-martian-database", "client_id": CLIENTID, "username": username, "password": password, } self._oauth_token(payload) def profiles(self): self._refresh_token() return self._session.get('https://profileapi.kayosports.com.au/user/profile').json() #landing has heros and panels def landing(self, name): params = { 'evaluate': 99, 'profile': userdata.get('profile'), } return self._session.get('https://vccapi.kayosports.com.au/content/types/landing/names/{}'.format(name), params=params).json() #panel has shows and episodes def panel(self, id): params = { #'evaluate': 3, 'profile': userdata.get('profile'), } return self._session.get('https://vccapi.kayosports.com.au/content/types/carousel/keys/{}'.format(id), params=params).json()[0] #show has episodes and panels def show(self, id): params = { 'evaluate': 99, 'profile': userdata.get('profile'), 'showCategory': id, } return self._session.get('https://vccapi.kayosports.com.au/content/types/landing/names/show', params=params).json() def event(self, id): params = { 'evaluate': 1, 'profile': userdata.get('profile'), 'event': id, } return self._session.get('https://vccapi.kayosports.com.au/content/types/landing/names/event', params=params).json()[0]['contents'][0]['data']['asset'] def sport(self, sport=None): params = { 'evaluate': 99, 'profile': userdata.get('profile'), 'sport': sport, } return self._session.get('https://vccapi.kayosports.com.au/content/types/landing/names/sport', params=params).json() def sport_menu(self, sport): return self._session.get('https://resources.kayosports.com.au/production/sport-menu/lists/{}.json'.format(sport)).json() def stream(self, asset): self._refresh_token() params = { 'fields': 'alternativeStreams', } data = self._session.post('https://vmndplay.kayosports.com.au/api/v1/asset/{}/play'.format(asset), params=params, json={}).json() if 'errors' in data: raise APIError(_(_.ASSET_ERROR, msg=data['errors'][0]['detail'])) return data['data'][0] def logout(self): userdata.delete('access_token') userdata.delete('refresh_token') userdata.delete('expires') userdata.delete('profile') self.new_session()
def new_session(self): self.logged_in = False self._session = Session(HEADERS, base_url=API_URL) self.set_access_token(userdata.get('access_token'))
class API(object): def new_session(self): self.logged_in = False self._session = Session(HEADERS, base_url=API_URL) self.set_access_token(userdata.get('access_token')) def set_access_token(self, token): if token: self._session.headers.update( {'Authorization': 'Bearer {0}'.format(token)}) self.logged_in = True def login(self, username, password): log('API: Login') data = {'response_type': 'token', 'lang': 'eng'} resp = self._session.get(LOGIN_URL, params=data) soup = BeautifulSoup(resp.text, 'html.parser') form = soup.find('form', id='new_signin') for e in form.find_all('input'): data[e.attrs['name']] = e.attrs.get('value') data.update({ 'signin[email]': username, 'signin[password]': password, }) resp = self._session.post(LOGIN_URL, data=data, allow_redirects=False) access_token = resp.cookies.get('showmax_oauth') if not access_token: self.logout() raise Error() self.set_access_token(access_token) data = self._session.get('user/current', params={'lang': 'eng'}).json() if 'error_code' in data: raise Error() device_id = hashlib.sha1(username).hexdigest().upper() userdata.set('device_id', device_id) userdata.set('access_token', access_token) userdata.set('user_id', data['user_id']) def catalogue(self, _params): def process_page(start): params = { 'field[]': [ 'id', 'images', 'title', 'items', 'total', 'type', 'description', 'videos' ], 'lang': 'eng', 'showmax_rating': 'adults', 'sort': 'alphabet', 'start': start, 'subscription_status': 'full' } params.update(_params) data = self._session.get('catalogue/assets', params=params).json() items = data['items'] count = int(data.get('count', 0)) remaining = int(data.get('remaining', 0)) if count > 0 and remaining > 0: items.extend(process_page(start + count)) return items return process_page(start=0) def shows(self): return self.catalogue({ 'type': 'tv_series', 'exclude_section[]': ['kids'], }) def movies(self): return self.catalogue({ 'type': 'movie', 'exclude_section[]': ['kids'], }) def kids(self): return self.catalogue({ 'section': 'kids', }) def show(self, show_id): params = { 'field[]': [ 'id', 'images', 'title', 'items', 'total', 'type', 'description', 'videos', 'number', 'seasons', 'episodes' ], 'lang': 'eng', 'showmax_rating': 'adults', 'subscription_status': 'full' } return self._session.get('catalogue/tv_series/{}'.format(show_id), params=params).json() def search(self, query): return self.catalogue({ 'q': query, }) def logout(self): log('API: Logout') userdata.delete('device_id') userdata.delete('access_token') userdata.delete('user_id') self.new_session() def play(self, video_id): params = { 'encoding': 'mpd_widevine_modular', 'subscription_status': 'full', 'lang': 'eng', } data = self._session.get('playback/play/{0}'.format(video_id), params=params).json() url = data['url'] task_id = data['packaging_task_id'] session_id = data['session_id'] data = { 'user_id': userdata.get('user_id'), 'video_id': video_id, 'hw_code': userdata.get('device_id'), 'packaging_task_id': task_id, 'session_id': session_id, } params = {'showmax_rating': 'adults', 'lang': 'eng'} data = self._session.post('playback/verify', params=params, data=data).json() license_request = data['license_request'] license_url = API_URL.format( 'drm/widevine_modular?license_request={0}'.format(license_request)) return url, license_url
def get_channels(): return Session().get(M3U8_URL).json()
def new_session(self): self.logged_in = False self._session = Session(HEADERS) self._set_authentication()
def epg(output, **kwargs): Session().chunked_dl(EPG_URL, output)
class API(object): def new_session(self): self.logged_in = False self._session = Session(HEADERS, base_url=API_URL) self._set_authentication() def _set_authentication(self): access_token = userdata.get('token') if not access_token: return self._session.headers.update({'X-Auth-Token': access_token}) self.logged_in = True def login(self, username, password): self.logout() payload = { 'email': username, 'password': password, 'platform': 'google', } data = self._session.post('/v1/login/', data=payload).json() if 'error' in data: try: msg = data['error']['message']['base'][0] except: msg = '' raise APIError(_(_.LOGIN_ERROR, msg=msg)) userdata.set('token', data['message']['auth_token']) self._set_authentication() @mem_cache.cached(CACHE_TIME) def categories(self): return self._session.get('/v1/categories').json()['data'] def series(self, id): return self._session.get('/v2/series/{}'.format(id)).json()['data'] @mem_cache.cached(CACHE_TIME) def featured(self): return self._session.get('/v2/featured').json() def sections(self, id, page=1): params = { 'cache': False, 'collections': True, 'media_limit': 36, 'page': page, } return self._session.get( '/v1/sections/{}/mobile'.format(id)).json()['data']['groups'] def collection(self, id, flattened=False): params = { 'flattened': flattened, } return self._session.get('/v2/collections/{}'.format(id), params=params).json()['data'] @mem_cache.cached(CACHE_TIME) def collections(self, flattened=False, excludeMedia=True, page=1): params = { 'flattened': flattened, 'excludeMedia': excludeMedia, 'limit': 20, 'page': page, } return self._session.get('/v2/collections', params=params).json() def filter_media(self, filterby, term=None, collections=True, page=1): params = { 'filterBy': filterby, 'collections': collections, 'limit': 20, 'page': page, } if term: params['term'] = term return self._session.get('/v1/media', params=params).json() def set_user_media(self, id, **kwargs): params = { 'media_id': id, #'is_bookmarked': 'true' if value else 'false', } params.update(kwargs) data = self._session.post('/v1/user_media', params=params, json={}).json() print(data) def get_subtitles(self, captions): subtitles = [] for idx, caption in enumerate(captions): try: r = self._session.get(caption['file']) reader = detect_format(r.text) srt = SRTWriter().write(reader().read(r.text)) except: log.debug('Failed to parse subtitle: {}'.format( caption['file'])) else: srtfile = xbmc.translatePath( 'special://temp/curiosity{}.{}.srt'.format( idx, caption['code'])).decode('utf-8') with codecs.open(srtfile, "w", "utf-8") as f: f.write(srt) subtitles.append(srtfile) return subtitles def media(self, id): # params = { # 'showEncodings': 'Android', #limits to 1080p # 'encodingsNew': 'true', #breaks playback # } return self._session.get('/v1/media/{}'.format(id)).json()['data'] def logout(self): userdata.delete('token') mem_cache.empty() self.new_session()