def race(slug, **kwargs): races = api.races() if slug not in races: raise Error(_.RACE_NOT_FOUND) race = races[slug] folder = plugin.Folder(race['title'], no_items_label=_.NO_STREAMS) for stream in race['streams']: if not stream['slug']: continue item = plugin.Item( label = stream['label'], path = plugin.url_for(play, slug=stream['slug']), playable = True, ) if stream['live']: item.label = _(_.LIVE_LABEL, title=stream['label']) item.context.append((_.PLAY_FROM_LIVE, "PlayMedia({})".format( plugin.url_for(play, slug=stream['slug'], play_type=PLAY_FROM_LIVE, _is_live=True) ))) item.context.append((_.PLAY_FROM_START, "PlayMedia({})".format( plugin.url_for(play, slug=stream['slug'], play_type=PLAY_FROM_START, _is_live=True) ))) item.path = plugin.url_for(play, slug=stream['slug'], play_type=settings.getEnum('live_play_type', PLAY_FROM_TYPES, PLAY_FROM_ASK), _is_live=True) folder.add_items([item]) return folder
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 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 _play_videos(videos): if not videos: plugin.exception('No videos found') default_audio = settings.getEnum('audio_lang', AUDIO_LANGS) if len(videos) == 1: chosen = videos[0] else: videos = sorted(videos, key=lambda x: x['language']) chosen = None for video in videos: if video['language']['iso_639_3'].lower() == default_audio: chosen = video break if not chosen: index = gui.select(_.SELECT_LANG, [x['language']['name'] for x in videos]) if index < 0: return chosen = videos[index] url, license_url = api.play(chosen['id']) item = plugin.Item( inputstream=inputstream.Widevine(license_url), path=url, headers=HEADERS, use_proxy= True, # Needed for https://github.com/xbmc/inputstream.adaptive/pull/606 ) return item
def _process_rows(rows): items = [] now = arrow.utcnow() for row in rows: try: thumb = IMG_URL.format( row.get('pictureID') or row['pictures']['16x9']) except: thumb = None start_time = arrow.get(row.get('startTime') or None) end_time = arrow.get(row.get('endTime') or None) now = arrow.utcnow() item = plugin.Item( label=row['name'], info={'plot': row.get('shortDescription')}, art={'thumb': thumb}, path=plugin.url_for(play, id=row['id']), playable=True, is_folder=False, ) if row.get('resourceType') == 'epg/stations': item.path = plugin.url_for(play, id=row['id'], _is_live=True) elif start_time < now and end_time > now: item.label += _(_.LIVE, _bold=True) if row.get('customAttributes', {}).get('isLinearChannelInLiveEvent') != 'true': item.context.append((_.PLAY_FROM_LIVE, "PlayMedia({})".format( plugin.url_for(play, id=row['id'], play_type=PLAY_FROM_LIVE, _is_live=True)))) item.context.append((_.PLAY_FROM_START, "PlayMedia({})".format( plugin.url_for(play, id=row['id'], play_type=PLAY_FROM_START, _is_live=True)))) item.path = plugin.url_for(play, id=row['id'], play_type=settings.getEnum( 'live_play_type', PLAY_FROM_TYPES, PLAY_FROM_ASK), _is_live=True) elif start_time > now.shift(seconds=10): item.label += start_time.to('local').format(_.DATE_FORMAT) items.append(item) return items
def editorial(id, title, **kwargs): folder = plugin.Folder(title) now = arrow.utcnow() live_play_type = settings.getEnum('live_play_type', PLAY_FROM_TYPES, default=PLAY_FROM_ASK) for row in api.editorial(id): is_live = row.get('isLive', False) is_linear = row.get('type') == 'linear-channel' item = plugin.Item( label=row['title'], info={ 'plot': row.get('description'), 'duration': row.get('duration', 0), }, art={'thumb': row.get('imageUrl') or DEFAULT_IMG}, path=plugin.url_for(play, asset=row['id'], _is_live=is_live), playable=True, is_folder=False, ) start_time = arrow.get( row['broadcastStartTime']) if 'broadcastStartTime' in row else None if start_time and start_time > now: item.label += start_time.to('local').format(_.DATE_FORMAT) elif is_linear: item.path = plugin.url_for(play, asset=row['id'], _is_live=is_live) elif is_live: item.label = _(_.LIVE, label=item.label) item.context.append((_.PLAY_FROM_LIVE, "PlayMedia({})".format( plugin.url_for(play, asset=row['id'], play_type=PLAY_FROM_LIVE, _is_live=is_live)))) item.context.append((_.PLAY_FROM_START, "PlayMedia({})".format( plugin.url_for(play, asset=row['id'], play_type=PLAY_FROM_START, _is_live=is_live)))) item.path = plugin.url_for(play, asset=row['id'], play_type=live_play_type, _is_live=is_live) folder.add_items(item) return folder
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 parse_game(game): item = plugin.Item( label=game.title, art={'thumb': game.image}, info={ 'title': game.title, 'plot': game.description, 'duration': game.duration, 'aired': game.aired, }, playable=True, ) if game.state in (Game.LIVE, Game.UPCOMING): item.path = plugin.url_for(play, slug=game.slug, game_type=Game.FULL, play_type=settings.getEnum( 'live_play_type', PLAY_FROM_TYPES, default=PLAY_FROM_ASK), _is_live=True) item.context.append((_.WATCH_LIVE, "PlayMedia({0})".format( plugin.url_for(play, slug=game.slug, game_type=Game.FULL, play_type=PLAY_FROM_LIVE, _is_live=True)))) item.context.append((_.WATCH_FROM_START, "PlayMedia({0})".format( plugin.url_for(play, slug=game.slug, game_type=Game.FULL, play_type=PLAY_FROM_START, _is_live=True)))) elif game.state == Game.PROCESSING: item.path = plugin.url_for(play, slug=game.slug, game_type=Game.FULL) item.context.append((_.FULL_GAME, "PlayMedia({0})".format(item.path))) elif game.state == Game.PLAYED: item.path = plugin.url_for(play, slug=game.slug, game_type=Game.FULL) item.context.append((_.FULL_GAME, "PlayMedia({0})".format(item.path))) item.context.append((_.CONDENSED_GAME, "PlayMedia({0})".format( plugin.url_for(play, slug=game.slug, game_type=Game.CONDENSED)))) if game.result: item.context.append( (_.SHOW_SCORE, "RunPlugin({0})".format(plugin.url_for(show_score, slug=game.slug)))) return item
def login(self, username, password): self.logout() self._create_session() data = { 'password': password, 'email': username, } data = self._session.post('proxy/login', data=data).json() if data['error']: raise APIError(_(_.LOGIN_ERROR, msg=data['error']['message'])) auth_token = data['result']['newAuthToken'] while True: selected = self._select_device(auth_token) if not selected: return data = { 'password': password, 'deviceId': selected['uniqueDeviceId'], 'email': username, } data = self._session.post('proxy/login', data=data).json() if data['error']: gui.error(data['error']['message']) else: break auth_token = data['result']['newAuthToken'] device_token = data['result']['deviceAuthToken'] userdata.set('device_token', device_token) data = { 'name': selected['name'], 'casDeviceId': selected['uniqueDeviceId'], 'type': selected['type'], } data = self._session.post('proxy/casAuth', data=data, headers={'X-AN-WebService-CustomerAuthToken': auth_token, 'X-AN-WebService-DeviceAuthToken': device_token}).json() if data['error']: raise APIError(data['error']['message']) self._set_auth(data['result']['newAuthToken']) mem_cache.delete('channels') if settings.getEnum('login_type', choices=LOGIN_TYPE, default=LOGIN_MULTI_IP) == LOGIN_PASSWORD: userdata.set('password', password) userdata.set('device_id', selected['uniqueDeviceId'])
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(video_id, play_type=None, **kwargs): url = api.play(video_id) play_type = int(play_type) if play_type else settings.getEnum( 'live_play_type', PLAY_FROM_TYPES, default=PLAY_FROM_ASK) is_live = ROUTE_LIVE_TAG in kwargs item = plugin.Item( path=url, inputstream=inputstream.HLS(live=is_live), ) # 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.properties['ResumeTime'] = '1' # item.properties['TotalTime'] = '1' # item.inputstream.force = True return item
def service(): alerts = userdata.get('alerts', []) if not alerts: return now = arrow.now() notify = [] _alerts = [] for id in alerts: asset = api.event(id) start = arrow.get(asset.get('preCheckTime', asset['transmissionTime'])) #If we are streaming and started less than 10 minutes ago if asset.get('isStreaming', False) and (now - start).total_seconds() <= 60 * 10: notify.append(asset) elif start > now: _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(): start_from = 1 start = arrow.get(asset['transmissionTime']) if start < now and 'preCheckTime' in asset: precheck = arrow.get(asset['preCheckTime']) if precheck < start: start_from = (start - precheck).seconds play(id=asset['id'], start_from=start_from, play_type=settings.getEnum('live_play_type', LIVE_PLAY_TYPES, default=FROM_CHOOSE))
def _parse_video(row): asset = row['asset'] display = row['contentDisplay'] alerts = userdata.get('alerts', []) now = arrow.now() start = arrow.get(asset['transmissionTime']) precheck = start if 'preCheckTime' in asset: precheck = arrow.get(asset['preCheckTime']) if precheck > start: precheck = start title = display['title'] or asset['title'] if 'heroHeader' in display: title += ' [' + display['heroHeader'].replace( '${DATE_HUMANISED}', _makeHumanised(now, start).upper()).replace( '${TIME}', _makeTime(start)) + ']' item = plugin.Item( label=title, art={ 'thumb': _get_image(asset, 'video', 'thumb'), 'fanart': _get_image(asset, 'video', 'fanart'), }, info={ 'plot': display.get('description'), 'plotoutline': display.get('description'), 'mediatype': 'video', }, playable=True, is_folder=False, ) is_live = False play_type = settings.getEnum('live_play_type', PLAY_FROM_TYPES, default=PLAY_FROM_ASK) start_from = ((start - precheck).seconds) if start_from < 1: start_from = 1 if now < start: is_live = True toggle_alert = plugin.url_for(alert, asset=asset['id'], title=asset['title']) if asset['id'] not in userdata.get('alerts', []): item.info['playcount'] = 0 item.context.append( (_.SET_REMINDER, "RunPlugin({})".format(toggle_alert))) else: item.info['playcount'] = 1 item.context.append( (_.REMOVE_REMINDER, "RunPlugin({})".format(toggle_alert))) elif asset['assetType'] == 'live-linear': is_live = True start_from = 0 play_type = PLAY_FROM_LIVE elif asset['isLive'] and asset.get('isStreaming', False): is_live = True item.context.append((_.PLAY_FROM_LIVE, "PlayMedia({})".format( plugin.url_for(play, id=asset['id'], play_type=PLAY_FROM_LIVE, _is_live=is_live)))) item.context.append((_.PLAY_FROM_START, "PlayMedia({})".format( plugin.url_for(play, id=asset['id'], start_from=start_from, play_type=PLAY_FROM_START, _is_live=is_live)))) item.path = plugin.url_for(play, id=asset['id'], start_from=start_from, play_type=play_type, _is_live=is_live) return item
def parse_game(game): item = plugin.Item( label = game.title, is_folder = False, playable = game.state != Game.UPCOMING, art = {'thumb': game.image}, info = { 'title': game.title, 'plot': game.description, 'duration': game.duration, 'aired': game.aired, }, ) if game.state == Game.UPCOMING: item.path = plugin.url_for(alerts, slug=game.slug) if game.id not in userdata.get('alerts', []): item.info['playcount'] = 0 item.context.append((_.SET_REMINDER, "RunPlugin({0})".format(item.path))) else: item.info['playcount'] = 1 item.context.append((_.REMOVE_REMINDER, "RunPlugin({0})".format(item.path))) elif game.state == Game.LIVE: item.path = plugin.url_for(play, slug=game.slug, game_type=Game.FULL, play_type=settings.getEnum('live_play_type', PLAY_FROM_TYPES, default=PLAY_FROM_ASK), _is_live=True) item.context.append((_.WATCH_LIVE, "PlayMedia({0})".format( plugin.url_for(play, slug=game.slug, game_type=Game.FULL, play_type=PLAY_FROM_LIVE, _is_live=True) ))) item.context.append((_.WATCH_FROM_START, "PlayMedia({0})".format( plugin.url_for(play, slug=game.slug, game_type=Game.FULL, play_type=PLAY_FROM_START, _is_live=True) ))) elif game.state == Game.PROCESSING: item.path = plugin.url_for(play, slug=game.slug, game_type=Game.FULL) item.context.append((_.FULL_GAME, "PlayMedia({0})".format(item.path))) elif game.state == Game.PLAYED: item.path = plugin.url_for(play, slug=game.slug, game_type=Game.FULL) item.context.append((_.FULL_GAME, "PlayMedia({0})".format(item.path))) item.context.append((_.CONDENSED_GAME, "PlayMedia({0})".format( plugin.url_for(play, slug=game.slug, game_type=Game.CONDENSED) ))) if game.result: item.context.append((_.SHOW_SCORE, "RunPlugin({0})".format( plugin.url_for(show_score, slug=game.slug) ))) return item
def _process_entries(entries): items = [] now = arrow.now() play_type = settings.getEnum('live_play_type', PLAY_FROM_TYPES, default=PLAY_FROM_ASK) for row in entries: if row.get('type') in ('posters', 'landscapes') and not row.get('hideTitle', False): items.append(plugin.Item( label = row['title'], #art = {'thumb': row.get('thumbnail')}, path = plugin.url_for(parse, url=row['url'], title=row['title']), )) elif row.get('programType') == 'series': items.append(plugin.Item( label = row['title'], art = {'thumb': _art(row['images']), 'fanart': _art(row['images'], 'fanart')}, info = { 'plot': row['description'], 'year': row['releaseYear'], }, path = plugin.url_for(series, series_id=row['id']), )) elif row.get('programType') == 'movie': item = plugin.Item( label = row['title'], info = { 'plot': row['description'], 'year': row['releaseYear'], 'duration': row['runtime'], 'mediatype': 'movie', }, art = {'thumb': _art(row['images']), 'fanart': _art(row['images'], 'fanart')}, playable = True, path = _get_play_path(program_id=row['id']), ) if row.get('liveStartDate'): is_live = False start_date = arrow.get(int(row['liveStartDate'])/1000) if row.get('liveEndDate'): end_date = arrow.get(int(row['liveEndDate']/1000)) else: end_date = start_date if start_date > now: item.label += ' [{}]'.format(start_date.humanize()) elif start_date < now and end_date > now: is_live = True item.label += ' [B][LIVE][/B]' if 'episode' in row: program_id = row['episode']['id'] if row['episode']['bonusFeature']: item.info['duration'] = None else: program_id = row['id'] item.path = _get_play_path(program_id=program_id, play_type=play_type, _is_live=is_live) if is_live: item.context.append((_.PLAY_FROM_LIVE, "PlayMedia({})".format( _get_play_path(program_id=row['id'], play_type=PLAY_FROM_LIVE, _is_live=is_live) ))) item.context.append((_.PLAY_FROM_START, "PlayMedia({})".format( _get_play_path(program_id=row['id'], play_type=PLAY_FROM_START, _is_live=is_live) ))) items.append(item) return items
def play(id, start_from=0, play_type=PLAY_FROM_LIVE, **kwargs): asset = api.stream(id) start_from = int(start_from) play_type = int(play_type) is_live = kwargs.get(ROUTE_LIVE_TAG) == ROUTE_LIVE_SUFFIX streams = [asset['recommendedStream']] streams.extend(asset['alternativeStreams']) streams = [s for s in streams if s['mediaFormat'] in SUPPORTED_FORMATS] if not streams: raise PluginError(_.NO_STREAM) prefer_cdn = settings.getEnum('prefer_cdn', AVAILABLE_CDNS) if prefer_cdn == CDN_AUTO: try: prefer_cdn = api.use_cdn(is_live)['useCDN'] except Exception as e: log.debug('Failed to get preferred cdn') prefer_cdn = None providers = [prefer_cdn] providers.extend([s['provider'] for s in streams]) streams = sorted(streams, key=lambda k: (providers.index(k['provider']), SUPPORTED_FORMATS.index(k['mediaFormat']))) stream = streams[0] log.debug('Stream CDN: {provider} | Stream Format: {mediaFormat}'.format( **stream)) item = plugin.Item( path=stream['manifest']['uri'], art=False, headers=HEADERS, ) item.headers.update( {'authorization': 'Bearer {}'.format(userdata.get('access_token'))}) if is_live and (play_type == PLAY_FROM_LIVE or (play_type == PLAY_FROM_ASK and gui.yes_no(_.PLAY_FROM, yeslabel=_.PLAY_FROM_LIVE, nolabel=_.PLAY_FROM_START))): play_type = PLAY_FROM_LIVE start_from = 0 ## Cloudfront streams start from correct position if stream['provider'] == CDN_CLOUDFRONT and start_from: start_from = 1 if stream['mediaFormat'] == FORMAT_DASH: item.inputstream = inputstream.MPD() elif stream['mediaFormat'] == FORMAT_HLS_TS: force = (is_live and play_type == PLAY_FROM_LIVE and asset['assetType'] != 'live-linear') item.inputstream = inputstream.HLS(force=force, live=is_live) if force and not item.inputstream.check(): raise PluginError(_.HLS_REQUIRED) elif stream['mediaFormat'] == FORMAT_HLS_FMP4: item.inputstream = inputstream.HLS(force=True, live=is_live) if not item.inputstream.check(): raise PluginError(_.HLS_REQUIRED) elif stream['mediaFormat'] in (FORMAT_DRM_DASH, FORMAT_DRM_DASH_HEVC): item.inputstream = inputstream.Widevine(license_key=LICENSE_URL, ) if start_from and not kwargs[ROUTE_RESUME_TAG]: item.properties['ResumeTime'] = start_from item.properties['TotalTime'] = start_from return item
def play(asset_id, **kwargs): use_ia_hls = settings.getBool('use_ia_hls') stream_data = api.get_stream_data(asset_id) token = userdata.get('access_token') play_item = plugin.Item( art=False, headers={'Authorization': 'Bearer {}'.format(token)}, cookies={ 'access_token': token, 'client_id': CLIENT_ID }, ) is_drm = stream_data.get('course_is_drmed', False) hls_url = stream_data.get('hls_url') if hls_url and not is_drm: play_item.path = hls_url play_item.inputstream = inputstream.HLS(live=False) return play_item stream_urls = stream_data.get('stream_urls') or {} streams = stream_urls.get('Video') or stream_urls.get('Audio') or [] CODECS = { 'libx264': 'H.264', 'libx265': 'H.265', } urls = [] qualities = [] for item in streams: if item['type'] != 'application/x-mpegURL': data = stream_data['data']['outputs'][item['label']] if data.get('migrated_from_non_labeled_conversions'): bandwidth, resolution = BANDWIDTH_MAP.get(int(item['label'])) codecs, fps = '', '' else: fps = _(_.QUALITY_FPS, fps=float(data['frame_rate'])) resolution = '{}x{}'.format(data['width'], data['height']) bandwidth = data[ 'video_bitrate_in_kbps'] * 1000 #(or total_bitrate_in_kbps) codecs = CODECS.get(data.get('video_codec'), '') urls.append([bandwidth, item['file']]) qualities.append([ bandwidth, _(_.QUALITY_BITRATE, bandwidth=float(bandwidth) / 1000000, resolution=resolution, fps=fps, codecs=codecs) ]) if not urls: for row in stream_data.get('media_sources') or []: if row['type'] == 'application/x-mpegURL' and 'encrypted-files' not in row[ 'src']: urls.append([row['src'], inputstream.HLS(live=False)]) if row['type'] == 'application/dash+xml': play_item.path = row['src'] if is_drm: token = stream_data['media_license_token'] ia = inputstream.Widevine(license_key=WV_URL.format( token=token)) else: ia = inputstream.MPD() urls.append([row['src'], ia]) if urls: urls = sorted(urls, key=lambda x: isinstance(x[1], inputstream.Widevine)) play_item.path = urls[0][0] play_item.inputstream = urls[0][1] if isinstance(play_item.inputstream, inputstream.Widevine): system, arch = get_system_arch() if system == 'Windows' or (system == 'Linux' and arch == 'armv7'): gui.ok(_.VMP_WARNING) return play_item if not urls: raise plugin.Error(_.NO_STREAM_ERROR) quality = kwargs.get(QUALITY_TAG) if quality is None: quality = settings.getEnum('default_quality', QUALITY_TYPES, default=QUALITY_ASK) else: quality = int(quality) urls = sorted(urls, key=lambda s: s[0], reverse=True) qualities = sorted(qualities, key=lambda s: s[0], reverse=True) if quality == QUALITY_CUSTOM: quality = int(settings.getFloat('max_bandwidth') * 1000000) elif quality == QUALITY_ASK: quality = select_quality(qualities) if quality == QUALITY_BEST: quality = qualities[0][0] elif quality == QUALITY_LOWEST: quality = qualities[-1][0] play_item.path = urls[-1][1] for item in urls: if item[0] <= quality: play_item.path = item[1] break return play_item
def load(self): self._region = settings.getEnum('region_index', REGIONS, default=REGION_US)
def epg(output, **kwargs): region = settings.getEnum('region', REGIONS, default=US) if region not in (LOCAL, CUSTOM): epg_url = MH_EPG_URL.format(region=region) try: Session().chunked_dl(epg_url, output) if epg_url.endswith('.gz'): gzip_extract(output) return True except Exception as e: log.exception(e) log.debug( 'Failed to get remote epg: {}. Fall back to scraping'.format( epg_url)) def process_epg(channels): count = 0 for id in channels: channel = channels[id] for row in channel.get('programs', []): start = arrow.get(row['start']).to('utc') stop = arrow.get(row['stop']).to('utc') title = row['title'] description = row['episode']['description'] subtitle = row['episode']['name'] category = row['episode']['genre'] icon = None if subtitle.lower().strip() == title.lower().strip(): subtitle = None f.write( u'<programme channel="{}" start="{}" stop="{}"><title>{}</title><desc>{}</desc>{}{}{}</programme>' .format( id, start.format('YYYYMMDDHHmmss Z'), stop.format('YYYYMMDDHHmmss Z'), escape(title), escape(description), u'<icon src="{}"/>'.format(escape(icon)) if icon else '', u'<sub-title>{}</sub-title>'.format(escape(subtitle)) if subtitle else '', u'<category>{}</category>'.format(escape(category)) if category else '', )) count += 1 return count HOUR_SHIFT = 6 now = arrow.now() start = now.replace(minute=0, second=0, microsecond=0).to('utc') stop = start.shift(hours=HOUR_SHIFT) END_TIME = start.shift(days=settings.getInt('epg_days', 3)) with codecs.open(output, 'w', encoding='utf8') as f: f.write(u'<?xml version="1.0" encoding="utf-8" ?><tv>') channels = api.epg(start, stop) for id in channels: f.write(u'<channel id="{id}"/>'.format(id=id)) added = process_epg(channels) while stop < END_TIME: start = stop stop = start.shift(hours=HOUR_SHIFT) channels = api.epg(start, stop) added = process_epg(channels) if added <= len(channels): break f.write(u'</tv>')
def _parse_video(asset): alerts = userdata.get('alerts', []) now = arrow.now() start = arrow.get(asset['transmissionTime']) precheck = start if asset['preCheckTime']: precheck = arrow.get(asset['preCheckTime']) if precheck > start: precheck = start # if 'heroHeader' in row['contentDisplay']: # title += ' [' + row['contentDisplay']['heroHeader'].replace('${DATE_HUMANISED}', _makeHumanised(now, start).upper()).replace('${TIME}', _makeTime(start)) + ']' item = plugin.Item( label=asset['title'], art={ 'thumb': asset['thumb'], 'fanart': asset['fanart'], }, info={ 'plot': asset['plot'], 'rating': asset.get('rating'), 'season': asset.get('season'), 'episode': asset.get('episode'), 'tvshowtitle': asset.get('showtitle'), 'duration': asset.get('duration'), 'year': asset.get('year'), 'mediatype': 'episode' if asset.get('episode') else 'movie', }, playable=True, is_folder=False, ) is_live = False play_type = settings.getEnum('live_play_type', PLAY_FROM_TYPES, default=PLAY_FROM_ASK) start_from = ((start - precheck).seconds) if start_from < 0: start_from = 0 if now < start: is_live = True toggle_alert = plugin.url_for(alert, asset=asset['asset_id'], title=asset['title']) if asset['asset_id'] not in userdata.get('alerts', []): item.info['playcount'] = 0 item.context.append( (_.SET_REMINDER, "RunPlugin({})".format(toggle_alert))) else: item.info['playcount'] = 1 item.context.append( (_.REMOVE_REMINDER, "RunPlugin({})".format(toggle_alert))) elif asset['type'] == 'live-linear': is_live = True start_from = 0 play_type = PLAY_FROM_START elif asset['playbackType'] == 'LIVE' and click['isStreaming']: is_live = True item.context.append((_.PLAY_FROM_LIVE, "PlayMedia({})".format( plugin.url_for(play, id=asset['asset_id'], play_type=PLAY_FROM_LIVE, _is_live=is_live)))) item.context.append((_.PLAY_FROM_START, "PlayMedia({})".format( plugin.url_for(play, id=asset['asset_id'], start_from=start_from, play_type=PLAY_FROM_START, _is_live=is_live)))) item.path = plugin.url_for(play, id=asset['asset_id'], start_from=start_from, play_type=play_type, _is_live=is_live) return item