def play(asset, play_type=PLAY_FROM_LIVE, **kwargs): play_type = int(play_type) from_start = False if play_type == PLAY_FROM_START or ( play_type == PLAY_FROM_ASK and not gui.yes_no(_.PLAY_FROM, yeslabel=_.PLAY_FROM_LIVE, nolabel=_.PLAY_FROM_START)): from_start = True stream = api.play(asset, True) item = plugin.Item( path=stream['url'], inputstream=inputstream.Widevine( license_key=stream['license']['@uri']), headers=HEADERS, ) drm_data = stream['license'].get('drmData') if drm_data: item.headers['x-axdrm-message'] = drm_data if from_start: item.resume_from = 1 return item
def play(livestream=None, brightcoveId=None, channel=None, **kwargs): if brightcoveId: item = api.get_brightcove_src(brightcoveId) elif livestream: item = plugin.Item(path=livestream, art=False, inputstream=inputstream.HLS(live=True)) if kwargs.get(ROUTE_LIVE_TAG) == ROUTE_LIVE_SUFFIX and not gui.yes_no( _.PLAY_FROM, yeslabel=_.PLAY_FROM_LIVE, nolabel=_.PLAY_FROM_START): item.properties['ResumeTime'] = '1' item.properties['TotalTime'] = '1' item.inputstream = inputstream.HLS(force=True, live=True) if not item.inputstream.check(): plugin.exception(_.LIVE_HLS_REQUIRED) elif channel: data = api.channel(channel) item = plugin.Item(path=data['publisherMetadata']['liveStreamUrl'], art=False, inputstream=inputstream.HLS(live=True)) item.headers = HEADERS return item
def logout(**kwargs): if not gui.yes_no(_.LOGOUT_YES_NO): return api.logout() userdata.delete('kid_lockdown') gui.refresh()
def _add_profile(taken_names, taken_avatars): ## PROFILE AVATAR ## options = [ plugin.Item(label=_(_.RANDOM_AVATAR, _bold=True)), ] values = [ ['_random', None], ] avatars = [] unused = [] for icon_set in api.profile_icons(): for row in icon_set['icons']: icon_info = [icon_set['iconSet'], row['iconIndex']] values.append(icon_info) avatars.append(icon_info) if row['iconImage'] in taken_avatars: label = _(_.AVATAR_USED, label=icon_set['label']) else: label = icon_set['label'] unused.append(icon_info) options.append( plugin.Item(label=label, art={'thumb': row['iconImage']})) index = gui.select(_.SELECT_AVATAR, options=options, useDetails=True) if index < 0: return avatar = values[index] if avatar[0] == '_random': avatar = random.choice(unused or avatars) ## PROFLE KIDS ## kids = gui.yes_no(_.KIDS_PROFILE_INFO, heading=_.KIDS_PROFILE) ## PROFILE NAME ## name = '' while True: name = gui.input(_.PROFILE_NAME, default=name).strip() if not name: return elif name.lower() in taken_names: gui.notification(_(_.PROFILE_NAME_TAKEN, name=name)) else: break ## ADD PROFILE ## profile = api.add_profile(name, icon_set=avatar[0], icon_index=avatar[1], kids=kids) if 'message' in profile: raise PluginError(profile['message']) _set_profile(profile)
def _play(program_id, play_type=None, is_live=False): play_type = int(play_type) if play_type else None program_data, play_data = api.play(program_id) headers = HEADERS.copy() headers['dt-custom-data'] = play_data['drm']['customData'] item = plugin.Item( path=play_data['videoUrl'], headers=headers, inputstream=inputstream.Widevine( license_key=play_data['drm']['licenseServerUrl'], license_data=play_data['drm']['init_data'], response='JBlicense', ), ) if is_live and ( play_type == PLAY_FROM_START or (play_type == PLAY_FROM_ASK and not gui.yes_no( _.PLAY_FROM, yeslabel=_.PLAY_FROM_LIVE, nolabel=_.PLAY_FROM_START)) ): item.resume_from = 1 for row in play_data.get('captions', []): item.subtitles.append([row['url'], row['language']]) # for chapter in program_data.get('chapters', []): # if chapter['name'] == 'Intro': # item.resume_from = str(chapter['end']/1000 - 1) # elif chapter['name'] == 'Credits': # item.play_next = {'time': chapter['start']/1000} return item
def check_alerts(): alerts = userdata.get('alerts', []) if not alerts: return for game in Game.select().where(Game.id << alerts): if game.state == Game.LIVE: alerts.remove(game.id) _to_start = game.start - arrow.utcnow().timestamp if settings.getInt('alert_when') == Alert.STREAM_START: message = _.STREAM_STARTED elif settings.getInt('alert_when') == Alert.KICK_OFF and _to_start > 0 and _to_start <= SERVICE_TIME: message = _.KICKOFF else: continue if settings.getInt('alert_type') == Alert.NOTIFICATION: gui.notification(message, heading=game.title, time=5000, icon=game.image) elif gui.yes_no(message, heading=game.title, yeslabel=_.WATCH, nolabel=_.CLOSE): _get_play_item(game, Game.FULL, play_type=settings.getEnum('live_play_type', PLAY_FROM_TYPES, default=PLAY_FROM_ASK)).play() elif game.state != Game.UPCOMING: alerts.remove(game.id) userdata.set('alerts', alerts)
def play(asset, play_type=PLAY_FROM_LIVE, **kwargs): play_type = int(play_type) from_start = False if play_type == PLAY_FROM_START or ( play_type == PLAY_FROM_ASK and not gui.yes_no(_.PLAY_FROM, yeslabel=_.PLAY_FROM_LIVE, nolabel=_.PLAY_FROM_START)): from_start = True stream = api.play(asset, True) item = plugin.Item( path=stream['url'], inputstream=inputstream.Widevine( license_key=stream['license']['@uri']), headers=HEADERS, ) drm_data = stream['license'].get('drmData') if drm_data: item.headers['x-axdrm-message'] = drm_data if from_start: item.properties['ResumeTime'] = '1' item.properties['TotalTime'] = '1' if kwargs.get(ROUTE_LIVE_TAG): item.inputstream.properties['manifest_update_parameter'] = 'full' return item
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 service(): api.refresh_token() alerts = userdata.get('alerts', []) if not alerts: return now = arrow.now() notify = [] _alerts = [] for id in alerts: entity = api.entitiy(id) if not entity: continue start = arrow.get(entity.get('startTime')) if now > start and (now - start).total_seconds() <= 60 * 10: notify.append(entity) elif now < start: _alerts.append(id) userdata.set('alerts', _alerts) for entity in notify: if not gui.yes_no(_(_.EVENT_STARTED, event=entity['name']), yeslabel=_.WATCH, nolabel=_.CLOSE): continue with signals.throwable(): play(id=entity['id'], play_type=settings.getEnum('live_play_type', LIVE_PLAY_TYPES, default=FROM_CHOOSE))
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 logout(**kwargs): if not gui.yes_no(_.LOGOUT_YES_NO): return api.logout() mem_cache.empty() gui.refresh()
def _interact_thread(): if gui.yes_no(news['message'], news.get('heading', _.NEWS_HEADING)): addon = get_addon(news['addon_id'], install=True) if not addon: return url = router.url_for('', _addon_id=news['addon_id']) xbmc.executebuiltin('ActivateWindow(Videos,{})'.format(url))
def install_service(**kwargs): with gui.progress(_.INSTALL_SERVICE, percent=100) as progress: restart_required = gpio.install() if restart_required and gui.yes_no(_.RESTART_REQUIRED): plugin.reboot() gui.refresh()
def delete_epg(epg_id, **kwargs): if not gui.yes_no('Are you sure you want to delete this EPG?'): return epg_id = int(epg_id) epg = EPG.get_by_id(epg_id) epg.delete_instance() gui.refresh()
def logout(**kwargs): if not gui.yes_no(_.LOGOUT_YES_NO): return api.logout() userdata.delete('avatar') userdata.delete('profile') userdata.delete('profile_name') gui.refresh()
def delete_epg(epg_id, **kwargs): if not gui.yes_no(_.CONF_DELETE_EPG): return epg_id = int(epg_id) epg = EPG.get_by_id(epg_id) epg.delete_instance() gui.refresh()
def _add_profile(taken_names, taken_avatars): ## PROFILE AVATAR ## options = [plugin.Item(label=_(_.RANDOM_AVATAR, _bold=True)),] values = ['_random',] avatars = {} unused = [] data = api.collection_by_slug('avatars', 'avatars') for container in data['containers']: if container['set']['contentClass'] == 'hidden': continue category = _get_text(container['set']['texts'], 'title', 'set') for row in container['set'].get('items', []): if row['images'][0]['url'] in taken_avatars: label = _(_.AVATAR_USED, label=category) else: label = category unused.append(row['avatarId']) options.append(plugin.Item(label=label, art={'thumb': row['images'][0]['url']})) values.append(row['avatarId']) avatars[row['avatarId']] = row['images'][0]['url'] index = gui.select(_.SELECT_AVATAR, options=options, useDetails=True) if index < 0: return avatar = values[index] if avatar == '_random': avatar = random.choice(unused or avatars.keys()) ## PROFLE KIDS ## kids = gui.yes_no(_.KIDS_PROFILE_INFO, heading=_.KIDS_PROFILE) ## PROFILE NAME ## name = '' while True: name = gui.input(_.PROFILE_NAME, default=name).strip() if not name: return elif name in taken_names: gui.notification(_(_.PROFILE_NAME_TAKEN, name=name)) else: break profile = api.add_profile(name, kids=kids, avatar=avatar) profile['_avatar'] = avatars[avatar] if 'errors' in profile: raise PluginError(profile['errors'][0].get('description')) _set_profile(profile)
def delete_playlist(playlist_id, **kwargs): if not gui.yes_no('Are you sure you want to delete this playlist?'): return playlist_id = int(playlist_id) playlist = Playlist.get_by_id(playlist_id) playlist.delete_instance() Playlist.update(order = Playlist.order - 1).where(Playlist.order >= playlist.order).execute() gui.refresh()
def delete_playlist(playlist_id, **kwargs): if not gui.yes_no(_.CONF_DELETE_PLAYLIST): return playlist_id = int(playlist_id) playlist = Playlist.get_by_id(playlist_id) playlist.delete_instance() Playlist.update(order = Playlist.order - 1).where(Playlist.order >= playlist.order).execute() gui.refresh()
def play(slug, play_type=PLAY_FROM_LIVE, **kwargs): item = api.play(slug) if ROUTE_LIVE_TAG in kwargs and item.inputstream: item.inputstream.live = True play_type = int(play_type) if play_type == PLAY_FROM_LIVE or (play_type == PLAY_FROM_ASK and not gui.yes_no(_.PLAY_FROM, yeslabel=_.PLAY_FROM_LIVE, nolabel=_.PLAY_FROM_START)): item.resume_from = 1 return item
def login(**kwargs): if config.has_device_link and gui.yes_no( _.LOGIN_WITH, yeslabel=_.DEVICE_LINK, nolabel=_.EMAIL_PASSWORD): result = _device_link() else: result = _email_password() if not result: return _select_profile() gui.refresh()
def reset_channel(slug, **kwargs): channel = Channel.get_by_id(slug) if channel.custom: if not gui.yes_no(_.CONF_DELETE_CHANNEL): return channel.delete_instance() Override.delete().where(Override.slug == channel.slug).execute() gui.refresh()
def _delete_profile(profiles): options = [] for index, profile in enumerate(profiles): options.append(plugin.Item(label=profile['name'], art={'thumb': profile['iconImage']['url']})) index = gui.select(_.SELECT_DELETE_PROFILE, options=options, useDetails=True) if index < 0: return selected = profiles[index] if gui.yes_no(_.DELETE_PROFILE_INFO, heading=_(_.DELTE_PROFILE_HEADER, name=selected['name'])) and api.delete_profile(selected['id']): gui.notification(_.PROFILE_DELETED, heading=selected['name'], icon=selected['iconImage']['url'])
def reset_channel(slug, **kwargs): channel = Channel.get_by_id(slug) if channel.custom: if not gui.yes_no('Are you sure you want to delete this channel?'): return channel.delete_instance() Override.delete().where(Override.slug == channel.slug).execute() gui.refresh()
def do_POST(self): url = self._get_url('POST') response = self._proxy_request('POST', url) if response.status_code in (406, ) and url == self._session.get( 'license_url') and not xbmc.getCondVisibility( 'System.Platform.Android') and gui.yes_no(_.WV_FAILED): thread = threading.Thread(target=inputstream.install_widevine, kwargs={'reinstall': True}) thread.start() self._output_response(response)
def new_epg(**kwargs): epg = EPG.user_create() if not epg: return if settings.getBool( 'ask_to_add', True) and epg.source_type != EPG.TYPE_ADDON and gui.yes_no( _.ADD_PLAYLIST): Playlist.user_create() gui.refresh()
def login(**kwargs): if gui.yes_no(_.LOGIN_WITH, yeslabel=_.DEVICE_LINK, nolabel=_.EMAIL_PASSWORD): result = _device_link() else: result = _email_password() if not result: return gui.refresh()
def _get_play_item(game, game_type, play_type=PLAY_FROM_LIVE): play_type = int(play_type) item = parse_game(game) is_live = game.state == Game.LIVE item.inputstream = inputstream.HLS(live=is_live) if play_type == PLAY_FROM_START or (play_type == PLAY_FROM_ASK and not gui.yes_no(_.PLAY_FROM, yeslabel=_.PLAY_FROM_LIVE, nolabel=_.PLAY_FROM_START)): item.properties['ResumeTime'] = '1' item.properties['TotalTime'] = '1' if is_live and not item.inputstream.check(): raise PluginError(_.HLS_REQUIRED) item.path = api.get_play_url(game, game_type) return item
def toggle_enabled(self): if self.enabled: self.enabled = False else: pin_used = Button.select( Button.id).where(Button.id != self.id, Button.pin == self.pin, Button.enabled == True).exists() if pin_used: if not gui.yes_no(_.DISABLE_OTHER_BTN): return False Button.update(enabled=False).where( Button.pin == self.pin).execute() self.enabled = True return True
def _add_profile(taken_names, taken_avatars): ## PROFILE AVATAR ## options = [ plugin.Item(label=_(_.RANDOM_AVATAR, _bold=True)), ] values = [ '_random', ] unused = [] for key in AVATARS: label = '' if key in taken_avatars: label = _(_.AVATAR_USED, label=label) else: unused.append(key) options.append(plugin.Item(label=label, art={'thumb': AVATARS[key]})) values.append(key) index = gui.select(_.SELECT_AVATAR, options=options, useDetails=True) if index < 0: return avatar = values[index] if avatar == '_random': avatar = random.choice(unused or AVATARS.keys()) ## PROFLE KIDS ## kids = gui.yes_no(_.KIDS_PROFILE_INFO, heading=_.KIDS_PROFILE) ## PROFILE NAME ## name = '' while True: name = gui.input(_.PROFILE_NAME, default=name).strip() if not name: return elif name in taken_names: gui.notification(_(_.PROFILE_NAME_TAKEN, name=name)) else: break profile = api.add_profile(name, kids, avatar) _set_profile(profile)