def service(): alerts = userdata.get('alerts', []) if not alerts: return now = arrow.now() notify = [] _alerts = [] for id in alerts: asset = api.asset(id) if 'broadcastStartTime' not in asset: continue start = arrow.get(asset['broadcastStartTime']) if now > start and (now - start).total_seconds() <= 60 * 10: notify.append(asset) elif now < start: _alerts.append(id) userdata.set('alerts', _alerts) for asset in notify: if not gui.yes_no(_(_.EVENT_STARTED, event=asset['title']), yeslabel=_.WATCH, nolabel=_.CLOSE): continue with signals.throwable(): play(asset['id'])
def login(self, username, password): try: payload = { 'email': username, 'password': password, } data = self._session.post( 'https://api.watchnebula.com/api/v1/auth/login/', json=payload).json() key = data.get('key') if not key: msg = data['non_field_errors'][0] raise APIError(msg) userdata.set('key', key) self._set_auth(key) data = self._session.get( 'https://api.watchnebula.com/api/v1/auth/user/', params={ 'from': 'Android' }, json={}).json() userdata.set('user_id', data['zobject_user_id']) self._token(force=True) except: self.logout() raise
def search(query=None, page=1, **kwargs): page = int(page) if not query: query = gui.input(_.SEARCH, default=userdata.get('search', '')).strip() if not query: return userdata.set('search', query) data = api.search(query=query, page=page) rows = data.get('item', []) page_number = data['paginationMetadata']['pageNumber'] page_size = data['paginationMetadata']['pageSize'] total_items = data['paginationMetadata'].get('totalCount', 0) total_pages = int(math.ceil(float(total_items) / page_size)) folder = plugin.Folder( _(_.SEARCH_FOR, query=query, page=page_number, total_pages=total_pages)) items = _process_items(rows) folder.add_items(items) if total_pages > page_number: folder.add_item( label=_(_.NEXT_PAGE, next=page_number + 1, total_pages=total_pages, _bold=True), path=plugin.url_for(search, query=query, page=page_number + 1), ) return folder
def search(query=None, page=1, **kwargs): page = int(page) if not query: query = gui.input(_.SEARCH, default=userdata.get('search', '')).strip() if not query: return userdata.set('search', query) folder = plugin.Folder(_(_.SEARCH_FOR, query=query)) data = api.search(query, page=page) hits = [x['hit'] for x in data['hits']] if data['resultsType'] == 'real' else [] items = _process_rows(hits) folder.add_items(items) if (data['meta']['page_size'] + data['meta']['offset']) < data['meta']['hits']: folder.add_item( label = _(_.NEXT_PAGE, page=page+1), path = plugin.url_for(search, query=query, page=page+1), specialsort = 'bottom', ) return folder
def service(): alerts = userdata.get('alerts', []) if not alerts: return data = api.live_matches() if not data['live']: return notify = [] for row in data['live']: if row['mid'] in alerts: alerts.remove(row['mid']) notify.append(row) userdata.set('alerts', alerts) for row in notify: if not gui.yes_no(_(_.MATCH_STARTED, match=row['subtitle']), yeslabel=_.WATCH, nolabel=_.CLOSE): continue with signals.throwable(): sources = row['stream']['video_sources'] priority = sources[0]['priority'] item = _play_live(match_id=row['mid'], priority=1) item.play()
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 login(self, username, password): self.require_token() payload = { 'Action': '/View/Account/SubmitLogin', 'jsonModel': json.dumps({ 'Username': username, 'Password': password, 'IsOnboarding': False, 'IsVoucher': False, }), 'captcha': '', } resp = self._session.post('/View/Account/SubmitLogin', json=payload) token = resp.cookies.get(TOKEN_COOKIE_KEY) if not token: raise APIError(_.LOGIN_ERROR) userdata.set('token', token) self._set_authentication()
def _device_id(self): device_id = userdata.get('device_id') if device_id: return device_id device_id = settings.get('device_id') try: mac_address = uuid.getnode() if mac_address != uuid.getnode(): mac_address = '' except: mac_address = '' system, arch = get_system_arch() device_id = device_id.format(username=userdata.get('username'), mac_address=mac_address, system=system).strip() if not device_id: device_id = uuid.uuid4() log.debug('Raw device id: {}'.format(device_id)) device_id = hash_6(device_id, length=16) log.debug('Hashed device id: {}'.format(device_id)) userdata.set('device_id', device_id) return device_id
def search_channel(query=None, radio=0, page=1, **kwargs): radio = int(radio) page = int(page) if not query: query = gui.input(_.SEARCH, default=userdata.get('search', '')).strip() if not query: return userdata.set('search', query) folder = plugin.Folder(_(_.SEARCH_FOR, query=query)) page_size = settings.getInt('page_size', 0) db_query = Channel.channel_list(radio=radio, page=page, search=query, page_size=page_size) items = _process_channels(db_query) folder.add_items(items) if len(items) == page_size: folder.add_item( label = _(_.NEXT_PAGE, page=page+1, _bold=True), path = plugin.url_for(search_channel, query=query, radio=radio, page=page+1), ) return folder
def search(query=None, page=1, **kwargs): page = int(page) if not query: query = gui.input(_.SEARCH, default=userdata.get('search', '')).strip() if not query: return userdata.set('search', query) data = api.search(query=query, page=page) pages = data['pages'] folder = plugin.Folder( _(_.SEARCH_FOR, query=query, page=page, total_pages=pages)) items = _parse_contents(data.get('results', [])) folder.add_items(items) if pages > page: folder.add_item( label=_(_.NEXT_PAGE, next=page + 1, total_pages=pages, _bold=True), path=plugin.url_for(search, query=query, page=page + 1), ) return folder
def search(**kwargs): query = gui.input(_.SEARCH, default=userdata.get('search', '')).strip() if not query: return userdata.set('search', query) folder = plugin.Folder(_(_.SEARCH_FOR, query=query)) for row in api.search(query): item = plugin.Item( label=row['title'], art={'thumb': row['image'].get('LARGE')}, info={}, ) if row['editorialItemType'] == 'Program': item.path = plugin.url_for(list_seasons, id=row['id']) elif row['editorialItemType'] == 'Video': item.path = plugin.url_for(play_video, id=row['id']) item.playable = True else: continue folder.add_items(item) return folder
def search(query=None, page=1, **kwargs): page = int(page) limit = 50 if not query: query = gui.input(_.SEARCH, default=userdata.get('search', '')).strip() if not query: return userdata.set('search', query) folder = plugin.Folder(_(_.SEARCH_FOR, query=query, page=page)) data = api.search(query, page=page, limit=limit) items = _process_entries(data['entries']) folder.add_items(items) if len(data['entries']) == limit: folder.add_item( label=_(_.NEXT_PAGE, next=page + 1, _bold=True), path=plugin.url_for(search, query=query, page=page + 1), ) return folder
def _set_ob_token(self): password = userdata.get('pswd') if password: ticket = self.login(userdata.get('username'), password) else: resp = self._session.post( 'https://auth.tab.co.nz/identity-service/api/v1/assertion/by-token', cookies={'OB-TGT': userdata.get('ob_tgt')}) if resp.status_code == 403: raise APIError(_.GEO_ERROR) elif resp.status_code != 201: raise APIError(_.AUTH_ERROR) else: ticket = resp.json()['data']['ticket'] resp = self._session.get( 'https://api.tab.co.nz/account-service/api/v1/account/header', headers={'Authentication': ticket}) if 'OB-TOKEN' not in self._session.cookies: raise APIError(_.AUTH_ERROR) userdata.set('ob_session', self._session.cookies['OB-SESSION'])
def select_quality(qualities): options = [] options.append([QUALITY_BEST, _.QUALITY_BEST]) options.extend(qualities) options.append([QUALITY_LOWEST, _.QUALITY_LOWEST]) values = [x[0] for x in options] labels = [x[1] for x in options] current = userdata.get('last_quality') default = -1 if current: try: default = values.index(current) except: default = values.index(qualities[-1][0]) for quality in qualities: if quality[0] <= current: default = values.index(quality[0]) break index = gui.select(_.PLAYBACK_QUALITY, labels, preselect=default, autoclose=10000) #autoclose after 10seconds if index < 0: raise FailedPlayback('User cancelled quality select') userdata.set('last_quality', values[index]) return values[index]
def del_favourite(id, **kwargs): favourites = userdata.get('favourites') or [] if id in favourites: favourites.remove(id) userdata.set('favourites', favourites) gui.refresh()
def configure_merge(**kwargs): data = _app_data() data['regions'].pop(ALL, None) user_regions = userdata.get('merge_regions', []) avail_regions = sorted( data['regions'], key=lambda x: (data['regions'][x]['sort'], data['regions'][x]['name'])) options = [] preselect = [] for index, code in enumerate(avail_regions): region = data['regions'][code] options.append( plugin.Item(label=region['name'], art={'thumb': region['logo']})) if code in user_regions: preselect.append(index) indexes = gui.select(heading=_.SELECT_REGIONS, options=options, multi=True, useDetails=True, preselect=preselect) if indexes is None: return user_regions = [avail_regions[i] for i in indexes] userdata.set('merge_regions', user_regions)
def configure_merge(**kwargs): user_providers = [x.lower() for x in userdata.get('merge_providers', [])] avail_providers = _providers(playlist=True) options = [] values = [] preselect = [] for index, key in enumerate( sorted(avail_providers, key=lambda x: (avail_providers[x]['sort'], avail_providers[x]['name']))): provider = avail_providers[key] values.append(key) options.append( plugin.Item(label=provider['name'], art={'thumb': provider['logo']})) if key in user_providers: preselect.append(index) indexes = gui.select(heading=_.SELECT_PROVIDERS, options=options, useDetails=True, multi=True, preselect=preselect) if indexes is None: return user_providers = [values[i] for i in indexes] userdata.set('merge_providers', user_providers)
def search(query=None, page=1, **kwargs): page = int(page) if not query: query = gui.input(_.SEARCH, default=userdata.get('search', '')).strip() if not query: return userdata.set('search', query) data = api.filter_media('keyword', query, page=page) total_pages = int(data['paginator']['total_pages']) folder = plugin.Folder( _(_.SEARCH_FOR, query=query, page=page, total_pages=total_pages)) for row in data['data']: item = _process_media(row) folder.add_items([item]) if total_pages > page: folder.add_item( label=_(_.NEXT_PAGE, next_page=page + 1), path=plugin.url_for(search, query=query, page=page + 1), ) return folder
def _set_token(self, token): data = jwt_data(token) expires = min(int(time.time() + 86400), data['exp'] - 10) userdata.set('expires', expires) userdata.set('token', token) self._set_authentication()
def _set_profile(profile, notify=True): api.set_profile(profile['id']) if settings.getBool('kid_lockdown', False) and profile['isKidsProfile']: userdata.set('kid_lockdown', True) if notify: gui.notification(_.PROFILE_ACTIVATED, heading=userdata.get('profile_name'), icon=userdata.get('profile_icon'))
def _create_session(self, force=False): self._config = self.get_config() platform = self._config['alpha_networks_dash'][REGION] self._session._base_url = platform['platform_url'] + '{}' self._session.headers.update({ 'X-AN-WebService-IdentityKey': platform['hss_key'], # hss_key, hls_key, chromecast_key }) if not self.logged_in or (not force and time.time() < userdata.get('token_expires')): return login_type = settings.getEnum('login_type', choices=LOGIN_TYPE, default=LOGIN_MULTI_IP) if login_type == LOGIN_MULTI_IP: # Single device, changing IP address (same as app) data = self._session.post('proxy/loginDevice', headers=self._auth_headers).json() elif login_type == LOGIN_MULTI_DEVICE: # Multiple device, static IP address data = self._session.post('proxy/casAvailableDevice', headers=self._auth_headers).json() elif login_type == LOGIN_PASSWORD: # Supports multiple devices and multiple IP address as long (as others also using password) data = { 'password': userdata.get('password'), 'deviceId': userdata.get('device_id'), 'email': userdata.get('username'), } data = self._session.post('proxy/login', data=data).json() if data['error']: error = _(_.TOKEN_ERROR, msg=data['error']['message']) if data['error']['code'] == -1: self.logout() gui.refresh() if login_type == LOGIN_MULTI_IP: error = _.LOGIN_MULTI_IP_ERROR elif login_type == LOGIN_MULTI_DEVICE: error = _.LOGIN_MULTI_DEVICE_ERROR raise APIError(error) if 'deviceAuthToken' in data['result']: userdata.set('device_token', data['result']['deviceAuthToken']) self._set_auth(data['result']['newAuthToken'])
def _save_auth(self, cookies): expires = None for cookie in cookies: if expires is None or cookie.expires < expires: expires = cookie.expires userdata.set('expires', min(expires, int(time() + 86400))) userdata.set('auth_cookies', cookies.get_dict()) 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()
def _parse_tokens(self, access_token, id_token): jwt = jwt_data(access_token) userdata.set('access_token', access_token) userdata.set('id_token', id_token) userdata.set('token_expires', int(time.time()) + (jwt['exp'] - jwt['iat'] - 30)) userdata.set('country', jwt['country']) userdata.set('package', jwt['package']) self._set_access_token(access_token)
def alert(asset, title, **kwargs): alerts = userdata.get('alerts', []) if asset not in alerts: alerts.append(asset) gui.notification(title, heading=_.REMINDER_SET) else: alerts.remove(asset) gui.notification(title, heading=_.REMINDER_REMOVED) userdata.set('alerts', alerts) gui.refresh()
def search(**kwargs): query = gui.input(_.SEARCH, default=userdata.get('search', '')).strip() if not query: return userdata.set('search', query) folder = plugin.Folder(_(_.SEARCH_FOR, query=query)) rows = api.search(query) folder.add_items(_parse_rows(rows)) return folder
def stop(self): if not self.started: return self._server.shutdown() self._server.server_close() self._server.socket.close() self._httpd_thread.join() self.started = False log.debug("API: Stopped") userdata.set('_playlist_url', '') userdata.set('_epg_url', '')
def add_favourite(id, **kwargs): data = _app_data() channel = data['regions'][ALL]['channels'].get(id) if not channel: return favourites = userdata.get('favourites') or [] if id not in favourites: favourites.append(id) userdata.set('favourites', favourites) gui.notification(_.MY_CHANNEL_ADDED, heading=channel['name'], icon=channel['logo'])
def start(): http = HTTP() monitor = xbmc.Monitor() restart_queued = False boot_merge = settings.getBool('boot_merge', False) set_kodi_string('_iptv_merge_force_run') while not monitor.waitForAbort(1): http.start() if settings.getBool('http_api', False) else http.stop() forced = get_kodi_string('_iptv_merge_force_run') or 0 if forced or boot_merge or (settings.getBool('auto_merge', True) and time.time() - userdata.get('last_run', 0) > settings.getInt('reload_time_hours', 12) * 3600): set_kodi_string('_iptv_merge_force_run', '1') url = router.url_for('run_merge', forced=int(forced)) dirs, files = xbmcvfs.listdir(url) result, msg = int(files[0][0]), unquote_plus(files[0][1:]) if result: restart_queued = True userdata.set('last_run', int(time.time())) set_kodi_string('_iptv_merge_force_run') if restart_queued and settings.getBool('restart_pvr', False): if forced: progress = gui.progressbg(heading='Reloading IPTV Simple Client') if KODI_VERSION > 18: restart_queued = False try: xbmcaddon.Addon(IPTV_SIMPLE_ID).setSetting('m3uPathType', '0') except Exception as e: pass elif forced or (not xbmc.getCondVisibility('Pvr.IsPlayingTv') and not xbmc.getCondVisibility('Pvr.IsPlayingRadio')): restart_queued = False kodi_rpc('Addons.SetAddonEnabled', {'addonid': IPTV_SIMPLE_ID, 'enabled': False}) wait_delay = 4 for i in range(wait_delay): if monitor.waitForAbort(1): break if forced: progress.update((i+1)*int(100/wait_delay)) kodi_rpc('Addons.SetAddonEnabled', {'addonid': IPTV_SIMPLE_ID, 'enabled': True}) if forced: progress.update(100) progress.close() boot_merge = False http.stop()
def search(**kwargs): query = gui.input(_.SEARCH, default=userdata.get('search', '')).strip() if not query: return userdata.set('search', query) folder = plugin.Folder(_(_.SEARCH_FOR, query=query)) provider = _providers()[ALL] items = _get_channels(provider['channels'], query=query) folder.add_items(items) return folder