def live_play(): channel = plugin.args["channel"][0] name = plugin.args["label"][0] prog = plugin.args["prog"][0] icon = ICON if "img" in plugin.args: icon = plugin.args["img"][0] for rtp_channel in RTP_CHANNELS: if rtp_channel["id"] == channel: streams = rtp_channel["streams"] for stream in streams: if stream["type"] == "hls": if requests.head(stream["url"], headers=HEADERS).status_code == 200: liz = ListItem( "[B][COLOR blue]{}[/B][/COLOR] ({})".format( kodiutils.compat_py23str(name), kodiutils.compat_py23str(prog))) liz.setArt({"thumb": icon, "icon": icon}) liz.setProperty('IsPlayable', 'true') liz.setPath("{}|{}".format(stream["url"], urlencode(HEADERS))) setResolvedUrl(plugin.handle, True, liz) break else: continue elif stream["type"] == "dashwv": is_helper = inputstreamhelper.Helper( 'mpd', drm='com.widevine.alpha') if is_helper.check_inputstream(): # Grab token src = requests.get(stream["tk"], headers=HEADERS).text tk = re.compile('k: \"(.+?)\"', re.DOTALL).findall(src) if tk: payload = '{"drm_info":[D{SSM}], "kid": "E13506F7439BEAE7DDF0489FCDDF7481", "token":"' + tk[ 0] + '"}' liz = ListItem( "[B][COLOR blue]{}[/B][/COLOR] ({})".format( kodiutils.compat_py23str(name), kodiutils.compat_py23str(prog))) liz.setPath(stream["url"]) liz.setProperty( 'inputstream.adaptive.license_type', 'com.widevine.alpha') liz.setProperty( 'inputstream.adaptive.manifest_type', 'mpd') liz.setProperty('inputstreamaddon', 'inputstream.adaptive') liz.setProperty( 'inputstream.adaptive.stream_headers', urlencode(HEADERS)) liz.setMimeType('application/dash+xml') liz.setProperty( 'inputstream.adaptive.license_key', '{}|{}|{}|'.format( stream["license"], "Content-Type=application/json", urllib.quote(payload))) liz.setContentLookup(False) setResolvedUrl(plugin.handle, True, liz)
def get_video_url(plugin, item_id, video_id, download_mode=False, **kwargs): if get_kodi_version() < 18: xbmcgui.Dialog().ok('Info', plugin.localize(30602)) return False is_helper = inputstreamhelper.Helper('mpd', drm='widevine') if not is_helper.check_inputstream(): return False headers = {'X-Requested-With': 'XMLHttpRequest'} resp_token = urlquick.get(URL_TOKEN_API, headers=headers, max_age=-1) session_token = resp_token.cookies['npo_session'] json_parser_token = json.loads(resp_token.text) api_token = json_parser_token['token'] # Build PAYLOAD payload = {"_token": api_token} cookies = {"npo_session": session_token} resp2 = urlquick.post(URL_TOKEN_ID % video_id, cookies=cookies, data=payload, max_age=-1) json_parser = json.loads(resp2.text) token_id = json_parser['token'] resp3 = urlquick.get(URL_STREAM % (video_id, token_id), max_age=-1) json_parser2 = json.loads(resp3.text) if "html" in json_parser2 and "Dit programma mag niet bekeken worden vanaf jouw locatie (33)." in json_parser2[ "html"]: plugin.notify('ERROR', plugin.localize(30713)) return False elif "html" in json_parser2 and "Dit programma is niet (meer) beschikbaar (15)." in json_parser2[ "html"]: plugin.notify('ERROR', plugin.localize(30710)) return False licence_url = json_parser2["stream"]["keySystemOptions"][0]["options"][ "licenseUrl"] licence_url_header = json_parser2["stream"]["keySystemOptions"][0][ "options"]["httpRequestHeaders"] xcdata_value = licence_url_header["x-custom-data"] item = Listitem() item.path = json_parser2["stream"]["src"] item.label = get_selected_item_label() item.art.update(get_selected_item_art()) item.info.update(get_selected_item_info()) if plugin.setting.get_boolean('active_subtitle'): item.subtitles.append(URL_SUBTITLE % video_id) item.property[INPUTSTREAM_PROP] = 'inputstream.adaptive' item.property['inputstream.adaptive.manifest_type'] = 'mpd' item.property['inputstream.adaptive.license_type'] = 'com.widevine.alpha' item.property[ 'inputstream.adaptive.license_key'] = licence_url + '|Content-Type=&User-Agent=Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3041.0 Safari/537.36&x-custom-data=%s|R{SSM}|' % xcdata_value return item
def get_live_url(plugin, item_id, video_id, **kwargs): if item_id == 'viavosges': is_helper = inputstreamhelper.Helper('mpd') if not is_helper.check_inputstream(): return False live_html = urlquick.get( URL_LIVE_VIAVOSGES, headers={'User-Agent': web_utils.get_random_ua()}, max_age=-1) root = live_html.parse() url_live_datas = URL_ROOT_VIAVOSGES + root.find( ".//div[@class='HDR_VISIO']").get('data-url') + '&mode=html' resp = urlquick.get(url_live_datas, headers={'User-Agent': web_utils.get_random_ua()}, max_age=-1) json_parser = json.loads(resp.text) item = Listitem() item.path = json_parser["files"]["auto"] item.property['inputstreamaddon'] = 'inputstream.adaptive' item.property['inputstream.adaptive.manifest_type'] = 'mpd' item.label = get_selected_item_label() item.art.update(get_selected_item_art()) item.info.update(get_selected_item_info()) return item else: if item_id == 'viamirabelle': live_html = urlquick.get( URL_LIVE_VIAMIRABELLE % item_id, headers={'User-Agent': web_utils.get_random_ua()}, max_age=-1) else: live_html = urlquick.get( URL_LIVE % item_id, headers={'User-Agent': web_utils.get_random_ua()}, max_age=-1) root = live_html.parse() list_lives_datas = root.findall('.//iframe') live_id = '' for live_datas in list_lives_datas: src_datas = live_datas.get('src') break if 'dailymotion' in src_datas: live_id = re.compile(r'dailymotion.com/embed/video/(.*?)[\?\"]' ).findall(src_datas)[0] return resolver_proxy.get_stream_dailymotion( plugin, live_id, False) elif 'infomaniak' in src_datas: player_id = src_datas.split('player=')[1] resp2 = urlquick.get( URL_STREAM_INFOMANIAK % player_id, headers={'User-Agent': web_utils.get_random_ua()}, max_age=-1) json_parser = json.loads(resp2.text) return 'https://' + json_parser["sPlaylist"] elif 'creacast' in src_datas: resp2 = urlquick.get( src_datas, headers={'User-Agent': web_utils.get_random_ua()}, max_age=-1) return re.compile(r'file\: \"(.*?)\"').findall(resp2.text)[0] else: live_id = re.compile(r'v=(.*?)\&').findall(src_datas)[0] stream_json = urlquick.post( URL_STREAM, data={ 'action': 'video_info', 'refvideo': live_id }, headers={'User-Agent': web_utils.get_random_ua()}, max_age=-1) stream_jsonparser = json.loads(stream_json.text) return stream_jsonparser["data"]["bitrates"]["hls"]
def get_video_url(plugin, item_id, video_id, download_mode=False, **kwargs): if get_kodi_version() < 18: video_json = urlquick.get(URL_JSON_VIDEO % video_id, headers={ 'User-Agent': web_utils.get_random_ua(), 'x-customer-name': 'm6web' }, max_age=-1) json_parser = json.loads(video_json.text) video_assets = json_parser['clips'][0]['assets'] if video_assets is None: plugin.notify('ERROR', plugin.localize(30721)) return False final_video_url = '' all_datas_videos_quality = [] all_datas_videos_path = [] for asset in video_assets: if 'http_h264' in asset["type"]: all_datas_videos_quality.append(asset["video_quality"]) all_datas_videos_path.append(asset['full_physical_path']) elif 'h264' in asset["type"]: manifest = urlquick.get( asset['full_physical_path'], headers={'User-Agent': web_utils.get_random_ua()}, max_age=-1) if 'drm' not in manifest.text: all_datas_videos_quality.append(asset["video_quality"]) all_datas_videos_path.append(asset['full_physical_path']) if len(all_datas_videos_quality) == 0: xbmcgui.Dialog().ok('Info', plugin.localize(30602)) return False elif len(all_datas_videos_quality) == 1: final_video_url = all_datas_videos_path[0] else: if DESIRED_QUALITY == "DIALOG": seleted_item = xbmcgui.Dialog().select( plugin.localize(LABELS['choose_video_quality']), all_datas_videos_quality) if seleted_item == -1: return False return all_datas_videos_path[seleted_item] elif DESIRED_QUALITY == "BEST": url_best = '' i = 0 for data_video in all_datas_videos_quality: if 'lq' not in data_video: url_best = all_datas_videos_path[i] i = i + 1 final_video_url = url_best else: final_video_url = all_datas_videos_path[0] if download_mode: return download.download_video(final_video_url) return final_video_url else: resp_js_id = urlquick.get(URL_GET_JS_ID_API_KEY) js_id = re.compile(r'client\-(.*?)\.bundle\.js').findall( resp_js_id.text)[0] resp = urlquick.get(URL_API_KEY % js_id) api_key = re.compile(r'\"eu1.gigya.com\"\,key\:\"(.*?)\"').findall( resp.text)[0] if plugin.setting.get_string('6play.login') == '' or\ plugin.setting.get_string('6play.password') == '': xbmcgui.Dialog().ok( 'Info', plugin.localize(30604) % ('6play', 'https://www.6play.fr')) return False # Build PAYLOAD payload = { "loginID": plugin.setting.get_string('6play.login'), "password": plugin.setting.get_string('6play.password'), "apiKey": api_key, "format": "jsonp", "callback": "jsonp_3bbusffr388pem4" } # LOGIN resp2 = urlquick.post(URL_COMPTE_LOGIN, data=payload, headers={ 'User-Agent': web_utils.get_random_ua(), 'referer': 'https://www.6play.fr/connexion' }) json_parser = json.loads( resp2.text.replace('jsonp_3bbusffr388pem4(', '').replace(');', '')) if "UID" not in json_parser: plugin.notify('ERROR', '6play : ' + plugin.localize(30711)) return False account_id = json_parser["UID"] account_timestamp = json_parser["signatureTimestamp"] account_signature = json_parser["UIDSignature"] is_helper = inputstreamhelper.Helper('mpd', drm='widevine') if not is_helper.check_inputstream(): return False # Build PAYLOAD headers payload_headers = { 'x-auth-gigya-signature': account_signature, 'x-auth-gigya-signature-timestamp': account_timestamp, 'x-auth-gigya-uid': account_id, 'x-customer-name': 'm6web' } token_json = urlquick.get(URL_TOKEN_DRM % (account_id, video_id), headers=payload_headers, max_age=-1) token_jsonparser = json.loads(token_json.text) token = token_jsonparser["token"] video_json = urlquick.get(URL_JSON_VIDEO % video_id, headers={ 'User-Agent': web_utils.get_random_ua(), 'x-customer-name': 'm6web' }, max_age=-1) json_parser = json.loads(video_json.text) video_assets = json_parser['clips'][0]['assets'] if video_assets is None: plugin.notify('ERROR', plugin.localize(30721)) return False subtitle_url = '' if plugin.setting.get_boolean('active_subtitle'): for asset in video_assets: if 'subtitle_vtt' in asset["type"]: subtitle_url = asset['full_physical_path'] for asset in video_assets: if 'usp_dashcenc_h264' in asset["type"]: item = Listitem() item.path = asset['full_physical_path'] if 'http' in subtitle_url: item.subtitles.append(subtitle_url) item.label = get_selected_item_label() item.art.update(get_selected_item_art()) item.info.update(get_selected_item_info()) item.property['inputstreamaddon'] = 'inputstream.adaptive' item.property['inputstream.adaptive.manifest_type'] = 'mpd' item.property[ 'inputstream.adaptive.license_type'] = 'com.widevine.alpha' item.property[ 'inputstream.adaptive.license_key'] = URL_LICENCE_KEY % token return item for asset in video_assets: if 'http_h264' in asset["type"]: if "hd" in asset["video_quality"]: item = Listitem() item.path = asset['full_physical_path'] if 'http' in subtitle_url: item.subtitles.append(subtitle_url) item.label = get_selected_item_label() item.art.update(get_selected_item_art()) item.info.update(get_selected_item_info()) return item return False
def play(sl, lid): #show plot params = { 'z': 'moviedetails', 'cs': '37186922715', 'd': '3', 'v': '4', 'm': lid } data = utils.call(sl, lambda: sl.library(params)) if 'description' not in data or xbmcgui.Dialog().yesno( heading=data['title'], line1=data['description'], nolabel=_addon.getLocalizedString(30804), yeslabel=_addon.getLocalizedString(30803)): params = {} if 'deals' in data and data['deals'] and 'n' in data['deals'][0]: params.update({'dn': data['deals'][0]['n']}) try: info = utils.call(sl, lambda: sl.library_info(lid, params)) except StreamNotResolvedException as e: xbmcgui.Dialog().ok(heading=data['title'], line1=_addon.getLocalizedString(30805)) xbmcplugin.setResolvedUrl(_handle, False, xbmcgui.ListItem()) return if info: is_helper = inputstreamhelper.Helper(info['protocol'], drm=info['drm']) if is_helper.check_inputstream(): playitem = xbmcgui.ListItem(path=info['path']) playitem.setProperty('inputstreamaddon', is_helper.inputstream_addon) playitem.setProperty('inputstream.adaptive.manifest_type', info['protocol']) playitem.setProperty('inputstream.adaptive.license_type', info['drm']) playitem.setProperty('inputstream.adaptive.license_key', info['key']) if 'subs' in data: params = {'z': 'subtitle', 'lng': sl._lang, 'id': lid} subs = utils.call(sl, lambda: sl.library(params)) if 'url' in subs: playitem.setSubtitles([subs['url']]) video_info = {} if 'title' in data: video_info.update({'title': data['title']}) if 'description' in data: video_info.update({'plot': data['description']}) if 'director' in data: video_info.update({'director': data['director']}) playitem.setInfo('video', video_info) if 'actors' in data: playitem.setCast([{'name': a} for a in data['actors']]) if 'poster' in data: playitem.setArt({'thumb': data['poster']}) xbmcplugin.setResolvedUrl(_handle, True, playitem) return xbmcgui.Dialog().ok(heading=data['title'], line1=_addon.getLocalizedString(30805)) xbmcplugin.setResolvedUrl(_handle, False, xbmcgui.ListItem())
def test_check_inputstream_rtmp(self): inputstreamhelper.system_os = lambda: 'Linux' platform.machine = lambda: 'x86_64' is_helper = inputstreamhelper.Helper('rtmp') is_installed = is_helper.check_inputstream() self.assertTrue(is_installed, True)
def update_play_info(provider, context, video_id, video_item, video_stream, use_play_data=True): settings = context.get_settings() ui = context.get_ui() resource_manager = provider.get_resource_manager(context) video_data = resource_manager.get_videos([video_id], suppress_errors=True) meta_data = video_stream.get('meta', None) thumb_size = settings.use_thumbnail_size() image = None video_item.video_id = video_id if meta_data: video_item.set_subtitles(meta_data.get('subtitles', None)) image = get_thumbnail(thumb_size, meta_data.get('images', {})) if 'headers' in video_stream: video_item.set_headers(video_stream['headers']) # set uses_dash video_item.set_use_dash(settings.use_dash()) license_info = video_stream.get('license_info', {}) if inputstreamhelper and \ license_info.get('proxy') and \ license_info.get('url') and \ license_info.get('token'): ishelper = inputstreamhelper.Helper('mpd', drm='com.widevine.alpha') ishelper.check_inputstream() video_item.set_license_key(license_info.get('proxy')) ui.set_home_window_property('license_url', license_info.get('url')) ui.set_home_window_property('license_token', license_info.get('token')) """ This is experimental. We try to get the most information out of the title of a video. This is not based on any language. In some cases this won't work at all. TODO: via language and settings provide the regex for matching episode and season. """ for regex in __RE_SEASON_EPISODE_MATCHES__: re_match = regex.search(video_item.get_name()) if re_match: if 'season' in re_match.groupdict(): video_item.set_season(int(re_match.group('season'))) if 'episode' in re_match.groupdict(): video_item.set_episode(int(re_match.group('episode'))) break if video_item.live: video_item.set_play_count(0) if image: if video_item.live: image = ''.join([image, '?ct=', get_thumb_timestamp()]) video_item.set_image(image) # set fanart video_item.set_fanart(provider.get_fanart(context)) if not video_data: return video_item # requires API # =============== yt_item = video_data[video_id] snippet = yt_item['snippet'] # crash if not conform play_data = yt_item['play_data'] video_item.live = snippet.get('liveBroadcastContent') == 'live' # set the title if not video_item.get_title(): video_item.set_title(snippet['title']) # duration if not video_item.live and use_play_data and play_data.get('total_time'): video_item.set_duration_from_seconds(float( play_data.get('total_time'))) else: duration = yt_item.get('contentDetails', {}).get('duration', '') if duration: duration = utils.datetime_parser.parse(duration) # we subtract 1 seconds because YouTube returns +1 second to much video_item.set_duration_from_seconds(duration.seconds - 1) if not video_item.live and use_play_data: # play count if play_data.get('play_count'): video_item.set_play_count(int(play_data.get('play_count'))) if play_data.get('played_percent'): video_item.set_start_percent(play_data.get('played_percent')) if play_data.get('played_time'): video_item.set_start_time(play_data.get('played_time')) if play_data.get('last_played'): video_item.set_last_played(play_data.get('last_played')) # plot channel_name = snippet.get('channelTitle', '') description = kodion.utils.strip_html_from_text(snippet['description']) if channel_name and settings.get_bool( 'youtube.view.description.show_channel_name', True): description = '%s[CR][CR]%s' % (ui.uppercase( ui.bold(channel_name)), description) video_item.set_studio(channel_name) # video_item.add_cast(channel_name) video_item.add_artist(channel_name) video_item.set_plot(description) # date time if 'publishedAt' in snippet and snippet['publishedAt']: date_time = utils.datetime_parser.parse(snippet['publishedAt']) video_item.set_year_from_datetime(date_time) video_item.set_aired_from_datetime(date_time) video_item.set_premiered_from_datetime(date_time) video_item.set_date_from_datetime(date_time) if not image: image = get_thumbnail(thumb_size, snippet.get('thumbnails', {})) if video_item.live and image: image = ''.join([image, '?ct=', get_thumb_timestamp()]) video_item.set_image(image) return video_item
def get_francetv_video_stream(plugin, id_diffusion, download_mode=False): geoip_value = web_utils.geoip() if not geoip_value: geoip_value = 'FR' resp = urlquick.get(URL_FRANCETV_CATCHUP_PROGRAM_INFO % (id_diffusion, geoip_value), max_age=-1) json_parser = resp.json() if 'video' not in json_parser: plugin.notify('ERROR', plugin.localize(30716)) return False all_video_datas = [] video_datas = json_parser['video'] # Implementer Caption (found case) # Implement DRM (found case) if video_datas['drm'] is not None: all_video_datas.append((video_datas['format'], video_datas['drm'], video_datas['token'])) else: all_video_datas.append((video_datas['format'], None, video_datas['token'])) url_selected = all_video_datas[0][2] if 'hls' in all_video_datas[0][0]: json_parser2 = json.loads( urlquick.get(url_selected, max_age=-1).text) final_video_url = json_parser2['url'] if download_mode: return download.download_video(final_video_url) return final_video_url elif 'dash' in all_video_datas[0][0]: if download_mode: xbmcgui.Dialog().ok(plugin.localize(14116), plugin.localize(30603)) return False is_helper = inputstreamhelper.Helper('mpd') if not is_helper.check_inputstream(): return False item = Listitem() item.property[INPUTSTREAM_PROP] = 'inputstream.adaptive' item.property['inputstream.adaptive.manifest_type'] = 'mpd' item.label = get_selected_item_label() item.art.update(get_selected_item_art()) item.info.update(get_selected_item_info()) if all_video_datas[0][1]: item.path = video_datas['url'] token_request = json.loads('{"id": "%s", "drm_type": "%s", "license_type": "%s"}' % (id_diffusion, video_datas['drm_type'], video_datas['license_type'])) token = urlquick.post(video_datas['token'], json=token_request).json()['token'] license_request = '{"token": "%s", "drm_info": [D{SSM}]}' % token license_key = 'https://widevine-proxy.drm.technology/proxy|Content-Type=application%%2Fjson|%s|' % quote_plus(license_request) item.property['inputstream.adaptive.license_type'] = 'com.widevine.alpha' item.property['inputstream.adaptive.license_key'] = license_key else: json_parser2 = json.loads( urlquick.get(url_selected, max_age=-1).text) item.path = json_parser2['url'] return item else: # Return info the format is not known return False
def get_video_url(plugin, item_id, video_id, download_mode=False, **kwargs): if item_id == 'swissinfo': channel_name_value = 'swi' else: channel_name_value = item_id resp = urlquick.get(URL_INFO_VIDEO % (channel_name_value, video_id)) json_parser = json.loads(resp.text) # build stream_url is_drm = False for stream_datas in json_parser["chapterList"]: if video_id in stream_datas["id"]: for stream_datas_url in stream_datas["resourceList"]: if 'drmList' in stream_datas_url: is_drm = True if is_drm: if get_kodi_version() < 18: xbmcgui.Dialog().ok(plugin.localize(14116), plugin.localize(30602)) return False is_helper = inputstreamhelper.Helper('mpd', drm='widevine') if not is_helper.check_inputstream(): return False if download_mode: return False licence_drm_url = '' for stream_datas in json_parser["chapterList"]: if video_id not in stream_datas["id"]: continue for stream_datas_url in stream_datas["resourceList"]: if 'DASH' not in stream_datas_url["streaming"]: continue stream_url = stream_datas_url["url"] for licence_drm_datas in stream_datas_url["drmList"]: if 'WIDEVINE' in licence_drm_datas["type"]: licence_drm_url = licence_drm_datas["licenseUrl"] item = Listitem() item.path = stream_url item.property[INPUTSTREAM_PROP] = 'inputstream.adaptive' item.property['inputstream.adaptive.manifest_type'] = 'mpd' item.property[ 'inputstream.adaptive.license_type'] = 'com.widevine.alpha' item.property[ 'inputstream.adaptive.license_key'] = licence_drm_url + '|Content-Type=&User-Agent=Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3041.0 Safari/537.36&Host=srg.live.ott.irdeto.com|R{SSM}|' item.label = get_selected_item_label() item.art.update(get_selected_item_art()) item.info.update(get_selected_item_info()) return item stream_url = '' for stream_datas in json_parser["chapterList"]: if video_id in stream_datas["id"]: is_token = False for stream_datas_url in stream_datas["resourceList"]: if stream_datas_url['tokenType'] == 'NONE': stream_url = stream_datas_url['url'] else: is_token = True if 'HD' in stream_datas_url["quality"] and \ 'mpegURL' in stream_datas_url["mimeType"]: stream_url = stream_datas_url["url"] break if 'mpegURL' in stream_datas_url["mimeType"]: stream_url = stream_datas_url["url"] if is_token: acl_value = '/i/%s/*' % ( re.compile(r'\/i\/(.*?)\/master').findall(stream_url)[0]) token_datas = urlquick.get(URL_TOKEN % acl_value, max_age=-1) token_jsonparser = json.loads(token_datas.text) token = token_jsonparser["token"]["authparams"] if '?' in stream_datas_url['url']: stream_url = stream_url + '&' + token else: stream_url = stream_url + '?' + token if download_mode: return download.download_video(stream_url) return stream_url
def getStreamParams(args, html): """Get stream parameters and check with InputStreamHelper: * Parse JWPlayer config using JSON and get stream parameters, fallback to old method in case of parsing errors * Check stream parameters with InputStreamHelper * Prepare parameters for xbmcgui.ListItem Parameters: args: plugin args class html: HTML page content with JWPlayer config Returns dict with following keys: 'legacy': use Kodi buildin playback (e.g. for HLS streams) 'url': stream url 'content-type': Content type (e.g. application/vnd.apple.mpegurl) 'properties': dict with parameters to pass to xbmcgui.ListItem.setProperty(key, value) """ try: # remove stuff that cannot be parsed by JSON parser html = html.replace("autostart: (autoplay) ? \"true\" : \"false\"", "autostart: \"false\"") # try parse with JSON result = get_stream_params_from_json( parse_stream_config(html, "jwplayer(\"jwplayer-container\").setup({")) except (ValueError, KeyError, TypeError): log(args, "Error parsing JWPlayer config, trying old method", xbmc.LOGNOTICE) # fallback to old method result = get_stream_params_fallback(html) if not result: log(args, "Invalid JWPlayer config", xbmc.LOGERROR) errdlg(args) return None log(args, "Stream proto '{0}' drm '{1}'".format(result['proto'], result['drm']), xbmc.LOGDEBUG) # prepare stream parameters if not result['url'].startswith("http"): result['url'] = "https://www.wakanim.tv" + result['url'] if result['proto'] == "hls": # play HLS with Kodi buildin playback return { 'legacy': True, 'url': result['url'] + getCookies(args), 'content-type': "application/vnd.apple.mpegurl", 'properties': {} } if result['proto'] == "dash": result['proto'] = "mpd" result['content-type'] = "application/dash+xml" else: log(args, "Unknown stream protocol '{0}'".format(result['proto']), xbmc.LOGNOTICE) if result['drm'] == "widevine": result['drm'] = "com.widevine.alpha" else: log(args, "Unknown stream license type '{0}'".format(result['drm']), xbmc.LOGNOTICE) # check stream parameters with InputStreamHelper try: if not inputstreamhelper.Helper(result['proto'], result['drm']).check_inputstream(): log(args, "InputStreamHelper: check stream failed", xbmc.LOGERROR) return None except inputstreamhelper.Helper.InputStreamException as e: log(args, "InputStreamHelper: {0}".format(e), xbmc.LOGERROR) errdlg(args) return None # prepare parameters for InputStream Adaptive a = "inputstream.adaptive" params = { 'inputstreamaddon': a, a + '.stream_headers': getCookies(args)[1:], a + '.manifest_type': result['proto'] } if result['drm']: params[a + '.license_type'] = result['drm'] headers = "" for k, v in list(result['headers'].items()): headers += urlencode({k: v}) + "&" headers += "User-Agent=Mozilla%2F5.0%20%28Windows%20NT%2010.0%3B%20Win64%3B%20x64%29%20AppleWebKit%2F537.36%20%28KHTML%2C%20like%20Gecko%29%20Chrome%2F60.0.3112.113%20Safari%2F537.36&Content-Type=text%2Fxml&SOAPAction=http%3A%2F%2Fschemas.microsoft.com%2FDRM%2F2007%2F03%2Fprotocols%2FAcquireLicense|R{SSM}|" params[a + '.license_key'] = result['key'] + "|" + headers return { 'legacy': False, 'url': result['url'], 'content-type': result.get('content-type'), 'properties': params }
def update_play_info(provider, context, video_id, video_item, video_stream): settings = context.get_settings() resource_manager = provider.get_resource_manager(context) video_data = resource_manager.get_videos([video_id]) meta_data = video_stream.get('meta', None) live = video_stream.get('Live', False) thumb_size = settings.use_thumbnail_size() image = None if meta_data: video_item.set_subtitles(meta_data.get('subtitles', None)) video_item.set_headers(meta_data.get('headers', '')) image = get_thumbnail(thumb_size, meta_data.get('images', {})) yt_item = video_data[video_id] snippet = yt_item['snippet'] # crash if not conform # set uses_dash video_item.set_use_dash(settings.use_dash()) # set mediatype video_item.set_mediatype('video') # using video if inputstreamhelper and video_stream.get('license_url'): ishelper = inputstreamhelper.Helper('mpd', drm='com.widevine.alpha') ishelper.check_inputstream() video_item.set_license_key(video_stream.get('license_url')) # set the title if not video_item.get_title(): video_item.set_title(snippet['title']) if not video_item.use_dash() and not settings.is_support_alternative_player_enabled() and \ video_item.get_headers() and video_item.get_uri().startswith('http'): video_item.set_uri(video_item.get_uri() + '|' + video_item.get_headers()) """ This is experimental. We try to get the most information out of the title of a video. This is not based on any language. In some cases this won't work at all. TODO: via language and settings provide the regex for matching episode and season. """ # video_item.set_season(1) # video_item.set_episode(1) for regex in __RE_SEASON_EPISODE_MATCHES__: re_match = regex.search(video_item.get_name()) if re_match: if 'season' in re_match.groupdict(): video_item.set_season(int(re_match.group('season'))) if 'episode' in re_match.groupdict(): video_item.set_episode(int(re_match.group('episode'))) break # plot channel_name = snippet.get('channelTitle', '') description = kodion.utils.strip_html_from_text(snippet['description']) if channel_name and settings.get_bool( 'youtube.view.description.show_channel_name', True): description = '[UPPERCASE][B]%s[/B][/UPPERCASE][CR][CR]%s' % ( channel_name, description) video_item.set_studio(channel_name) # video_item.add_cast(channel_name) video_item.add_artist(channel_name) video_item.set_plot(description) # date time if 'publishedAt' in snippet: date_time = utils.datetime_parser.parse(snippet['publishedAt']) video_item.set_year_from_datetime(date_time) video_item.set_aired_from_datetime(date_time) video_item.set_premiered_from_datetime(date_time) video_item.set_date_from_datetime(date_time) # duration duration = yt_item.get('contentDetails', {}).get('duration', '') duration = utils.datetime_parser.parse(duration) # we subtract 1 seconds because YouTube returns +1 second to much video_item.set_duration_from_seconds(duration.seconds - 1) if not image: image = get_thumbnail(thumb_size, snippet.get('thumbnails', {})) if live and image: image += '?ct=' + get_thumb_timestamp() video_item.set_image(image) # set fanart video_item.set_fanart(provider.get_fanart(context)) return video_item
def play_video(endpoint, metadata, epgdata): #### # # Play a video by the provided path. # # Parameters: # path: Fully-qualified video URL # #### global __session__ global cookiejar logger.debug('Enter function') logger.debug('Called with parameters: endpoint = ' + endpoint) logger.debug('Called with parameters: metadata = ' + str(metadata)) logger.debug('Called with parameters: epgdata = ' + str(epgdata)) # Set a flag so we know whether to enter in the last "if" clause known_video_type = 0 _channel_metadata_ = json.loads(metadata) _channel_epgdata_ = json.loads(epgdata) logger.info('Play channel: ' + _channel_metadata_['new-info']['meta']['channelName']) logger.debug('Play channel: ' + _channel_metadata_['new-info']['meta']['channelName']) logger.debug('_channel_metadata_[\'shortcode\'] = ' + _channel_metadata_['shortcode']) if _channel_metadata_['shortcode'] == 'livestream': logger.debug('Playing a \'livestream\' video.') # Set the flag so we won't enter in the last "if" clause known_video_type = 1 # Get the stream data (contains the URL for the stream to be played) MyHeaders = { 'Host': 'www.digionline.ro', 'Referer': 'https://www.digionline.ro' + endpoint, 'Origin': 'https://www.digionline.ro', 'X-Requested-With': 'XMLHttpRequest', 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8', 'User-Agent': userAgent, 'Accept': '*/*', 'Accept-Language': 'en-US', 'Accept-Encoding': 'identity', 'Connection': 'keep-alive', 'Upgrade-Insecure-Requests': '1' } MyPostData = { 'id_stream': _channel_metadata_['new-info']['meta']['streamId'], 'quality': 'hq' } logger.debug('Cookies: ' + str(list(cookiejar))) logger.debug('Headers: ' + str(MyHeaders)) logger.debug('MyPostData: ' + str(MyPostData)) logger.debug('URL: https://www.digionline.ro' + _channel_metadata_['new-info']['meta']['streamUrl']) logger.debug('Method: POST') # Send the POST request _request_ = __session__.post( 'https://www.digionline.ro' + _channel_metadata_['new-info']['meta']['streamUrl'], data=MyPostData, headers=MyHeaders) logger.debug('Received status code: ' + str(_request_.status_code)) logger.debug('Received cookies: ' + str(list(cookiejar))) logger.debug('Received headers: ' + str(_request_.headers)) logger.debug('Received data: ' + _request_.content) _stream_data_ = json.loads(_request_.content) logger.debug('_stream_data_ = ' + str(_stream_data_)) # Get the host needed to be set in the headers _headers_host_ = re.findall('//(.+?)/', _stream_data_['stream_url'], re.IGNORECASE)[0] logger.debug('Found: _headers_host_ = ' + _headers_host_) # If needed, append the "https:" to the stream_url if 'https://' not in _stream_data_['stream_url']: _stream_url_ = 'https:' + _stream_data_['stream_url'] logger.debug('Created: _stream_url_ = ' + _stream_url_) else: _stream_url_ = _stream_data_['stream_url'] logger.debug('Found: _stream_url_ = ' + _stream_url_) # Set the headers to be used with imputstream.adaptive _headers_ = '' _headers_ = _headers_ + 'Host=' + _headers_host_ _headers_ = _headers_ + '&User-Agent=' + userAgent _headers_ = _headers_ + '&Referer=' + 'https://www.digionline.ro' + endpoint _headers_ = _headers_ + '&Origin=https://www.digionline.ro' _headers_ = _headers_ + '&Connection=keep-alive' _headers_ = _headers_ + '&Accept-Language=en-US' _headers_ = _headers_ + '&Accept=*/*' _headers_ = _headers_ + '&Accept-Encoding=identity' logger.debug('Created: _headers_ = ' + _headers_) # Create a playable item with a path to play. # See: https://github.com/peak3d/inputstream.adaptive/issues/131#issuecomment-375059796 play_item = xbmcgui.ListItem(path=_stream_url_) play_item.setProperty('inputstreamaddon', 'inputstream.adaptive') play_item.setProperty('inputstream.adaptive.stream_headers', _headers_) play_item.setProperty('inputstream.adaptive.manifest_type', 'hls') play_item.setMimeType('application/vnd.apple.mpegurl') play_item.setContentLookup(False) # Pass the item to the Kodi player. xbmcplugin.setResolvedUrl(_handle, True, listitem=play_item) if _channel_metadata_['shortcode'] == 'nagra-livestream': logger.debug('Playing a \'nagra-livestream\' video.') # Set the flag so we won't enter in the last if clause known_video_type = 1 for cookie in cookiejar: if cookie.name == "deviceId": _deviceId_ = cookie.value logger.debug(' _deviceID_ = ' + _deviceId_) # Get the stream data (contains the URL for the stream to be played) MyHeaders = { 'Host': 'www.digionline.ro', 'Referer': 'https://www.digionline.ro' + endpoint, 'Origin': 'https://www.digionline.ro', 'X-Requested-With': 'XMLHttpRequest', 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8', 'User-Agent': userAgent, 'Accept': '*/*', 'Accept-Language': 'en-US', 'Accept-Encoding': 'identity', 'Connection': 'keep-alive', 'Upgrade-Insecure-Requests': '1' } MyPostData = { 'id_stream': _channel_metadata_['new-info']['meta']['streamId'], 'quality': 'hq', 'id_device': _deviceId_ } logger.debug('Cookies: ' + str(list(cookiejar))) logger.debug('Headers: ' + str(MyHeaders)) logger.debug('MyPostData: ' + str(MyPostData)) logger.debug('URL: https://www.digionline.ro' + _channel_metadata_['new-info']['meta']['streamUrl']) logger.debug('Method: POST') # Send the POST request _request_ = __session__.post( 'https://www.digionline.ro' + _channel_metadata_['new-info']['meta']['streamUrl'], data=MyPostData, headers=MyHeaders) logger.debug('Received status code: ' + str(_request_.status_code)) logger.debug('Received cookies: ' + str(list(cookiejar))) logger.debug('Received headers: ' + str(_request_.headers)) logger.debug('Received data: ' + _request_.content) _stream_data_ = json.loads(_request_.content) logger.debug('_stream_data_ = ' + str(_stream_data_)) if _stream_data_['error']['error_code'] == 0: logger.debug('_stream_data_[\'error\'][\'error_code\'] = ' + str(_stream_data_['error']['error_code'])) # Get the host needed to be set in the headers for the manifest file _headers_host_ = re.findall( '//(.+?)/', _stream_data_['data']['content']['stream.manifest.url'], re.IGNORECASE)[0] logger.debug('Found: _headers_host_ = ' + _headers_host_) # If needed, append the "https:" to the stream_url if 'https://' not in _stream_data_['data']['content'][ 'stream.manifest.url']: _stream_manifest_url_ = 'https:' + _stream_data_['data'][ 'content']['stream.manifest.url'] logger.debug('Created: _stream_manifest_url_ = ' + _stream_manifest_url_) else: _stream_manifest_url_ = _stream_data_['data']['content'][ 'stream.manifest.url'] logger.debug('Found: _stream_manifest_url_ = ' + _stream_manifest_url_) # Set the headers to be used with imputstream.adaptive _headers_ = '' _headers_ = _headers_ + 'Host=' + _headers_host_ _headers_ = _headers_ + '&User-Agent=' + userAgent _headers_ = _headers_ + '&Referer=' + 'https://www.digionline.ro' + endpoint _headers_ = _headers_ + '&Origin=https://www.digionline.ro' _headers_ = _headers_ + '&Connection=keep-alive' _headers_ = _headers_ + '&Accept-Language=en-US' _headers_ = _headers_ + '&Accept=*/*' _headers_ = _headers_ + '&Accept-Encoding=identity' logger.debug('Created: _headers_ = ' + _headers_) # Get the host needed to be set in the headers for the DRM license request _lic_headers_host_ = re.findall( '//(.+?)/', _stream_data_['data']['content']['widevine.proxy'], re.IGNORECASE)[0] logger.debug('Found: _lic_headers_host_ = ' + _lic_headers_host_) # Set the headers to be used when requesting license key _lic_headers_ = '' _lic_headers_ = _lic_headers_ + 'Host=' + _lic_headers_host_ _lic_headers_ = _lic_headers_ + '&User-Agent=' + userAgent _lic_headers_ = _lic_headers_ + '&Referer=' + 'https://www.digionline.ro' + endpoint _lic_headers_ = _lic_headers_ + '&Origin=https://www.digionline.ro' _lic_headers_ = _lic_headers_ + '&Connection=keep-alive' _lic_headers_ = _lic_headers_ + '&Accept-Language=en-US' _lic_headers_ = _lic_headers_ + '&Accept=*/*' _lic_headers_ = _lic_headers_ + '&Accept-Encoding=identity' _lic_headers_ = _lic_headers_ + '&verifypeer=false' logger.debug('Created: _lic_headers_ = ' + _lic_headers_) # Create a playable item with a path to play. ### See: ### https://github.com/peak3d/inputstream.adaptive/wiki ### https://github.com/peak3d/inputstream.adaptive/wiki/Integration ### https://github.com/emilsvennesson/script.module.inputstreamhelper is_helper = inputstreamhelper.Helper('mpd', drm='com.widevine.alpha') if is_helper.check_inputstream(): play_item = xbmcgui.ListItem(path=_stream_manifest_url_) play_item.setProperty('inputstreamaddon', 'inputstream.adaptive') play_item.setProperty('inputstream.adaptive.license_type', 'com.widevine.alpha') play_item.setProperty('inputstream.adaptive.manifest_type', 'mpd') play_item.setProperty( 'inputstream.adaptive.license_key', _stream_data_['data']['content']['widevine.proxy'] + '|' + _lic_headers_ + '|R{SSM}|') play_item.setMimeType('application/dash+xml') # Pass the item to the Kodi player. xbmcplugin.setResolvedUrl(_handle, True, listitem=play_item) else: # The DigiOnline.ro account configured in the addon's settings is not entitled to play this stream. logger.debug('_stream_data_[\'error\'][\'error_code\'] = ' + str(_stream_data_['error']['error_code'])) logger.debug('_stream_data_[\'error\'][\'error_message\'] = ' + _stream_data_['error']['error_message']) logger.info('[Error code: ' + str(_stream_data_['error']['error_code']) + '] => ' + _stream_data_['error']['error_message']) logger.debug('[Error code: ' + str(_stream_data_['error']['error_code']) + '] => ' + _stream_data_['error']['error_message']) xbmcgui.Dialog().ok( '[Error code: ' + str(_stream_data_['error']['error_code']) + ']', _stream_data_['error']['error_message']) # A 'catch-all'-type condition to cover for the unknown cases if known_video_type == 0: logger.info('Don\'t know (yet ?) how to play a \'' + _channel_metadata_['shortcode'] + '\' video type.') logger.debug('Don\'t know (yet ?) how to play a \'' + _channel_metadata_['shortcode'] + '\' video type.') logger.debug('Exit function')
def get_video_url(plugin, item_id, video_id, download_mode=False, **kwargs): if get_kodi_version() < 18: xbmcgui.Dialog().ok(plugin.localize(14116), plugin.localize(30602)) return False is_helper = inputstreamhelper.Helper('mpd', drm='widevine') if not is_helper.check_inputstream(): return False headers_auth = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:97.0) Gecko/20100101 Firefox/97.0", "Accept": "application/json, text/plain, */*", "Accept-Language": "fr,fr-FR;q=0.8,en-US;q=0.5,en;q=0.3", "Content-Type": "application/json;charset=utf-8", "Sec-Fetch-Dest": "empty", "Sec-Fetch-Mode": "cors", "Sec-Fetch-Site": "same-site", "Pragma": "no-cache", "Cache-Control": "no-cache" } json_body = { "device": { "deviceId": FAKE_DEVICE_ID, "width": 1920, "height": 1080, "type": "WEB", "name": "Windows Mozilla Firefox 97" }, "deviceId": FAKE_DEVICE_ID } resp = urlquick.post(URL_TV5MONDEPLUS_AUTH_ANONYMOUS_API, json=json_body, headers=headers_auth) json_parser = resp.json() headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:97.0) Gecko/20100101 Firefox/97.0", "Accept": "application/json, text/plain, */*", "Accept-Language": "fr,fr-FR;q=0.8,en-US;q=0.5,en;q=0.3", 'authorization': 'Bearer %s' % json_parser["sessionToken"], "Sec-Fetch-Dest": "empty", "Sec-Fetch-Mode": "cors", "Sec-Fetch-Site": "same-site", "Pragma": "no-cache", "Cache-Control": "no-cache", "referrer": "https://www.tv5mondeplus.com/" } params = { "ifa": FAKE_DEVICE_ID, "deviceType": "Desktop", "width": "1920", "height": "1080", "pageUrl": "https%3A%2F%2Fwww.tv5mondeplus.com%2Fplayer%2F" + video_id, "domain": "www.tv5mondeplus.com", "mute": "false", "autoplay": "true" } resp2 = urlquick.get(URL_STREAM_DATA % video_id, params=params, headers=headers) json_parser2 = resp2.json() item = Listitem() item.path = json_parser2["formats"][0]["mediaLocator"] item.property[INPUTSTREAM_PROP] = 'inputstream.adaptive' item.property['inputstream.adaptive.manifest_type'] = 'mpd' item.property['inputstream.adaptive.license_type'] = 'com.widevine.alpha' header_license = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:97.0) Gecko/20100101 Firefox/97.0", "Accept": "*/*", "Accept-Language": "fr,fr-FR;q=0.8,en-US;q=0.5,en;q=0.3", "Sec-Fetch-Dest": "empty", "Sec-Fetch-Mode": "cors", "Sec-Fetch-Site": "same-site", "Pragma": "no-cache", "Cache-Control": "no-cache", "referrer": "https://www.tv5mondeplus.com/" } license_server_url = json_parser2["formats"][0]["drm"][ "com.widevine.alpha"]["licenseServerUrl"] item.property['inputstream.adaptive.license_key'] = '%s|%s|R{SSM}|' \ % (license_server_url, urlencode(header_license)) item.label = get_selected_item_label() item.art.update(get_selected_item_art()) item.info.update(get_selected_item_info()) return item
def get_live_url(plugin, item_id, video_id, item_dict, **kwargs): if cqu.get_kodi_version() < 18: xbmcgui.Dialog().ok('Info', plugin.localize(30602)) return False resp_js_id = urlquick.get(URL_GET_JS_ID_API_KEY) js_id = re.compile(r'client\-(.*?)\.bundle\.js').findall( resp_js_id.text)[0] resp = urlquick.get(URL_API_KEY % js_id) api_key = re.compile( r'\"sso-login.rtl.be\"\,cdn\:\"eu1.gigya.com\"\,key\:\"(.*?)\"' ).findall(resp.text)[0] if plugin.setting.get_string('rtlplaybe.login') == '' or\ plugin.setting.get_string('rtlplaybe.password') == '': xbmcgui.Dialog().ok( 'Info', plugin.localize(30604) % ('RTLPlay (BE)', 'https://www.rtlplay.be')) return False # Build PAYLOAD payload = { "loginID": plugin.setting.get_string('rtlplaybe.login'), "password": plugin.setting.get_string('rtlplaybe.password'), "apiKey": api_key, "format": "jsonp", "callback": "jsonp_3bbusffr388pem4" } # LOGIN resp2 = urlquick.post(URL_COMPTE_LOGIN, data=payload, headers={ 'User-Agent': web_utils.get_random_ua, 'referer': 'https://www.rtlplay.be/connexion' }) json_parser = json.loads( resp2.text.replace('jsonp_3bbusffr388pem4(', '').replace(');', '')) if "UID" not in json_parser: plugin.notify('ERROR', 'RTLPlay (BE) : ' + plugin.localize(30711)) return False account_id = json_parser["UID"] account_timestamp = json_parser["signatureTimestamp"] account_signature = json_parser["UIDSignature"] is_helper = inputstreamhelper.Helper('mpd', drm='widevine') if not is_helper.check_inputstream(): return False # Build PAYLOAD headers payload_headers = { 'x-auth-gigya-signature': account_signature, 'x-auth-gigya-signature-timestamp': account_timestamp, 'x-auth-gigya-uid': account_id, 'User-Agent': web_utils.get_random_ua, 'x-customer-name': 'rtlbe' } channel = 'rtlbe_' + item_id token_json = urlquick.get(URL_TOKEN_DRM % (account_id, 'dashcenc_%s' % (channel)), headers=payload_headers, max_age=-1) token_jsonparser = json.loads(token_json.text) token = token_jsonparser["token"] video_json = urlquick.get(URL_LIVE_JSON % (channel), headers={ 'User-Agent': web_utils.get_random_ua, 'x-customer-name': 'rtlbe' }, max_age=-1) json_parser = json.loads(video_json.text) if not json_parser[channel]: plugin.notify('ERROR', plugin.localize(30712)) return False video_assets = json_parser[channel][0]['live']['assets'] if not video_assets: plugin.notify('INFO', plugin.localize(30716)) return False subtitle_url = '' if plugin.setting.get_boolean('active_subtitle'): for asset in video_assets: if 'subtitle_vtt' in asset["type"]: subtitle_url = asset['full_physical_path'] for asset in video_assets: if 'delta_dashcenc_h264' in asset["type"]: item = Listitem() item.path = asset['full_physical_path'] if 'http' in subtitle_url: item.subtitles.append(subtitle_url) item.property['inputstreamaddon'] = 'inputstream.adaptive' item.property['inputstream.adaptive.manifest_type'] = 'mpd' item.property[ 'inputstream.adaptive.license_type'] = 'com.widevine.alpha' item.property[ 'inputstream.adaptive.license_key'] = URL_LICENCE_KEY % token if item_dict: if 'label' in item_dict: item.label = item_dict['label'] if 'info' in item_dict: item.info.update(item_dict['info']) if 'art' in item_dict: item.art.update(item_dict['art']) else: item.label = LABELS[item_id] item.art["thumb"] = "" item.art["icon"] = "" item.art["fanart"] = "" item.info["plot"] = LABELS[item_id] return item return False
def test_check_inputstream_rtmp(self): inputstreamhelper.system_os = lambda: 'Linux' is_helper = inputstreamhelper.Helper('rtmp', drm='com.widevine.alpha') is_helper._arch = lambda: 'x86_64' is_installed = is_helper.check_inputstream() self.assertTrue(is_installed, True)
def install_widevine(): is_helper = inputstreamhelper.Helper('mpd', drm='com.widevine.alpha') return is_helper._check_drm()
def O0O0Ooo(args): if 77 - 77: o0oOOo0O0Ooo / OoooooooOO iI11i1ii11.SaveCredential(IIII()) if 46 - 46: o0oOOo0O0Ooo % iIii1I11I1II1.iII111i % iII111i + i11iIiiIii O0O0Oo00 = args.get('contentid') oOO00O = args.get('uicode') Oo00o0OO0O00o = O0O0O() if 82 - 82: I11i + OoooooooOO - i1IIi.i1IIi oo00o0Oo0oo(O0O0Oo00 + ' - ' + oOO00O, False) iIi1i, I1i11111i1i11, OOoOOO0, I1I1i = iI11i1ii11.GetStreamingURL( O0O0Oo00, oOO00O, Oo00o0OO0O00o) if 1 - 1: I11i % OOooOOo + O0 + i1IIi - OoO0O00 if 22 - 22: I1IiiI % I1ii11iIi11i o0oo0O = '%s|Cookie=%s' % (iIi1i, I1i11111i1i11) oo00o0Oo0oo(o0oo0O, False) if 13 - 13: i11iIiiIii + i1IIi * iIii1I11I1II1 % OoooooooOO - II111iiii * OOooOOo if iIi1i == '': ooO00oOoo(__language__(30303).encode('utf8')) return if 26 - 26: OoooooooOO * I1IiiI + OOooOOo IiIii1i111 = xbmcgui.ListItem(path=o0oo0O) if 43 - 43: O0 if OOoOOO0: if 39 - 39: I1IiiI.iIii1I11I1II1 * Ii1I % ooOoO0o.iIii1I11I1II1 if 54 - 54: OOooOOo IiI11ii1I = OOoOOO0['customdata'] IiiiI = OOoOOO0['drmhost'] if 61 - 61: OOooOOo % OOooOOo * o0oOOo0O0Ooo / o0oOOo0O0Ooo o0oOO = 'mpd' O0o0OO0000ooo = 'com.widevine.alpha' if 4 - 4: Ii1I OO0oOOoo = inputstreamhelper.Helper(o0oOO, drm=O0o0OO0000ooo) if 52 - 52: o0oOOo0O0Ooo % Oo0Ooo if OO0oOOoo.check_inputstream(): if 64 - 64: O0 % I11i % O0 * OoO0O00.oO0o + I1IiiI if oOO00O == 'movie': O00I11ii1i1 = 'https://www.wavve.com/player/movie?movieid=%s' % O0O0Oo00 else: O00I11ii1i1 = 'https://www.wavve.com/player/vod?programid=%s&page=1' % O0O0Oo00 if 78 - 78: iII111i iIiIIIIIii = { 'content-type': 'application/octet-stream', 'origin': 'https://www.wavve.com', 'pallycon-customdata': IiI11ii1I, 'referer': O00I11ii1i1, 'sec-fetch-mode': 'cors', 'sec-fetch-site': 'same-site', 'user-agent': oo00 } OOo0 = IiiiI + '|' + urllib.urlencode(iIiIIIIIii) + '|R{SSM}|' if 25 - 25: OoooooooOO + IiII * I1ii11iIi11i IiIii1i111.setProperty('inputstreamaddon', OO0oOOoo.inputstream_addon) IiIii1i111.setProperty('inputstream.adaptive.manifest_type', o0oOO) IiIii1i111.setProperty('inputstream.adaptive.license_type', O0o0OO0000ooo) if 92 - 92: I1IiiI + I11i + O0 / o0oOOo0O0Ooo + I1Ii111 IiIii1i111.setProperty('inputstream.adaptive.license_key', OOo0) IiIii1i111.setProperty('inputstream.adaptive.stream_headers', 'Cookie=%s' % I1i11111i1i11) if 18 - 18: ooOoO0o * OoOoOO00.iII111i / I1ii11iIi11i / i11iIiiIii xbmcplugin.setResolvedUrl(i1I1iI, True, IiIii1i111) if 21 - 21: oO0o / I1ii11iIi11i + Ii1I + OoooooooOO if I1I1i: ooO00oOoo(I1I1i.encode('utf-8')) else: if '/preview.' in urlparse.urlsplit(iIi1i).path: ooO00oOoo(__language__(30401).encode('utf8')) if 91 - 91: i11iIiiIii / i1IIi + iII111i + ooOoO0o * i11iIiiIii if args.get('mode') in [ 'VOD', 'MOVIE' ] and args.get('title') and args.get('viewage') != '21': oOoOO0 = { 'code': args.get('programid') if args.get('mode') == 'VOD' else args.get('contentid'), 'img': args.get('thumbnail'), 'title': args.get('title'), 'subtitle': args.get('subtitle') } OoOoOo00o0(args.get('mode').lower(), oOoOO0) if 90 - 90: Oo0Ooo % O0 * iIii1I11I1II1.iII111i if 8 - 8: ooOoO0o + II111iiii / iII111i / I11i if 74 - 74: O0 / i1IIi if 78 - 78: OoooooooOO.OoO0O00 + ooOoO0o - i1IIi
def get_video_url(plugin, item_id, next_url, download_mode=False, **kwargs): if 'www.mycanal.fr' in next_url: if get_kodi_version() < 18: xbmcgui.Dialog().ok('Info', plugin.localize(30602)) return False is_helper = inputstreamhelper.Helper('mpd', drm='widevine') if not is_helper.check_inputstream(): return False if download_mode: xbmcgui.Dialog().ok('Info', plugin.localize(30603)) return False # Get DeviceId header_device_id = { 'referer': 'https://secure-player.canal-plus.com/one/prod/v2/', } resp_device_id = urlquick.get(URL_DEVICE_ID, headers=header_device_id, max_age=-1) device_id = re.compile(r'deviceId\"\:\"(.*?)\"').findall( resp_device_id.text)[0] # Get Portail Id session_requests = requests.session() resp_app_config = session_requests.get(URL_REPLAY % item_id) json_app_config = re.compile('window.app_config=(.*?)};').findall( resp_app_config.text)[0] json_app_config_parser = json.loads(json_app_config + ('}')) portail_id = json_app_config_parser["api"]["pass"][ "portailIdEncrypted"] # Get PassToken payload = { 'deviceId': 'unknown', 'vect': 'INTERNET', 'media': 'PC', 'portailId': portail_id } resp_token_mycanal = session_requests.post(URL_TOKEN, data=payload) json_token_parser = json.loads(resp_token_mycanal.text) pass_token = json_token_parser["response"]["passToken"] video_id = next_url.split('/')[-1] headers = { 'Accept': 'application/json, text/plain, */*', 'Authorization': 'PASS Token="%s"' % pass_token, 'Content-Type': 'application/json; charset=UTF-8', 'XX-DEVICE': 'pc %s' % device_id, 'XX-DOMAIN': 'cpfra', 'XX-OPERATOR': 'pc', 'XX-Profile-Id': '0', 'XX-SERVICE': 'mycanal', 'User-Agent': web_utils.get_random_ua() } value_datas_json = session_requests.get(URL_VIDEO_DATAS % video_id, headers=headers) value_datas_jsonparser = json.loads(value_datas_json.text) comMode_value = '' contentId_value = '' distMode_value = '' distTechnology_value = '' drmType_value = '' functionalType_value = '' hash_value = '' idKey_value = '' quality_value = '' for stream_datas in value_datas_jsonparser["available"]: if 'Widevine' in stream_datas["drmType"]: comMode_value = stream_datas['comMode'] contentId_value = stream_datas['contentId'] distMode_value = stream_datas['distMode'] distTechnology_value = stream_datas['distTechnology'] drmType_value = stream_datas['drmType'] functionalType_value = stream_datas['functionalType'] hash_value = stream_datas['hash'] idKey_value = stream_datas['idKey'] quality_value = stream_datas['quality'] payload = { 'comMode': comMode_value, 'contentId': contentId_value, 'distMode': distMode_value, 'distTechnology': distTechnology_value, 'drmType': drmType_value, 'functionalType': functionalType_value, 'hash': hash_value, 'idKey': idKey_value, 'quality': quality_value } payload = json.dumps(payload) headers = { 'Accept': 'application/json, text/plain, */*', 'Authorization': 'PASS Token="%s"' % pass_token, 'Content-Type': 'application/json; charset=UTF-8', 'XX-DEVICE': 'pc %s' % device_id, 'XX-DOMAIN': 'cpfra', 'XX-OPERATOR': 'pc', 'XX-Profile-Id': '0', 'XX-SERVICE': 'mycanal', 'User-Agent': web_utils.get_random_ua() } resp_stream_datas = session_requests.put(URL_STREAM_DATAS, data=payload, headers=headers) jsonparser_stream_datas = json.loads(resp_stream_datas.text) resp_real_stream_datas = session_requests.get( jsonparser_stream_datas['@medias'], headers=headers) jsonparser_real_stream_datas = json.loads(resp_real_stream_datas.text) item = Listitem() item.path = jsonparser_real_stream_datas["VF"][0]["media"][0][ "distribURL"] + '/manifest' item.label = get_selected_item_label() item.art.update(get_selected_item_art()) item.info.update(get_selected_item_info()) item.property['inputstreamaddon'] = 'inputstream.adaptive' item.property['inputstream.adaptive.manifest_type'] = 'ism' item.property[ 'inputstream.adaptive.license_type'] = 'com.widevine.alpha' value_pass_token = 'PASS Token="%s"' % pass_token headers2 = { 'Accept': 'application/json, text/plain, */*', 'Authorization': value_pass_token, 'Content-Type': 'text/plain', 'User-Agent': web_utils.get_random_ua(), 'Origin': 'https://www.mycanal.fr', 'XX-DEVICE': 'pc %s' % device_id, 'XX-DOMAIN': 'cpfra', 'XX-OPERATOR': 'pc', 'XX-Profile-Id': '0', 'XX-SERVICE': 'mycanal', } # Return HTTP 200 but the response is not correctly interpreted by inputstream (https://github.com/peak3d/inputstream.adaptive/issues/267) item.property[ 'inputstream.adaptive.license_key'] = jsonparser_stream_datas[ '@licence'] + '?drmType=DRM%20Widevine' + '|%s|R{SSM}|' % urlencode( headers2) # return item Script.notify("INFO", plugin.localize(LABELS['drm_notification']), Script.NOTIFY_INFO) return False else: resp = urlquick.get(next_url, headers={'User-Agent': web_utils.get_random_ua()}, max_age=-1) json_parser = json.loads(resp.text) return json_parser["detail"]["informations"]["playsets"]["available"][ 0]["videoURL"]
def play_video(plugin, streamId, **kwargs): plugin.log('play_video streamId: %s' % streamId, lvl=plugin.DEBUG) EMAIL = plugin.setting.get_string('username') PASSWORD = plugin.setting.get_string('password') playout_url = PLAYOUT_URL % streamId PLAYOUT_HEADERS = get_headers() plugin.log('Fetching url: %s' % playout_url, lvl=plugin.DEBUG) try: Response = urlquick.get(playout_url, headers=PLAYOUT_HEADERS) except urlquick.HTTPError as err: plugin.log('HTTPError: %s' % err, lvl=plugin.DEBUG) if '422 Client Error' in str(err) and EMAIL and PASSWORD: plugin.notify(plugin.localize(30209), plugin.localize(30206), display_time=5000, sound=True) elif '422 Client Error' in str(err): plugin.notify(plugin.localize(30209), plugin.localize(30207), display_time=5000, sound=True) else: plugin.notify(plugin.localize(30209), plugin.localize(30205), display_time=5000, sound=True) return False jsonstr = Response.json() video_url = jsonstr['playout']['url'] drm = jsonstr['playout']['drm'] plugin.log('Playing: %s' % video_url, lvl=plugin.DEBUG) item = Listitem() item.label = getInfoLabel('ListItem.Label') item.path = video_url item.property[INPUTSTREAM_PROP] = 'inputstream.adaptive' headers = {'User-Agent': USER_AGENT} if drm and 'm3u8' not in video_url: is_helper = inputstreamhelper.Helper('ism', drm='com.widevine.alpha') if is_helper.check_inputstream(): params = get_filter(requesttype='request', assetId=streamId) headers = { 'User-Agent': USER_AGENT, 'BROWSER_NAME': 'CHROME', 'SHAHID_OS': 'LINUX', 'BROWSER_VERSION': '79.0' } Response = urlquick.get(requrl, params=params, headers=headers).json() licenceurl = Response['signature'] authority = 'shahiddotnet.keydelivery.westeurope.media.azure.net' LICENSE_TEMP = '%s|authority=%s&origin=%s&User-Agent=%s&referer=%s|R{SSM}|' URL_LICENCE_KEY = LICENSE_TEMP % (licenceurl, authority, BASE_URL, USER_AGENT, BASE_URL) item.property['inputstream.adaptive.manifest_type'] = 'ism' item.property[ 'inputstream.adaptive.license_type'] = 'com.widevine.alpha' item.property['inputstream.adaptive.license_key'] = URL_LICENCE_KEY else: return False else: item.property['inputstream'] = 'inputstream.adaptive' item.property['inputstream.adaptive.manifest_type'] = 'hls' return item
def test_check_inputstream_hls_again(self): inputstreamhelper.system_os = lambda: 'Linux' platform.machine = lambda: 'armv7' is_helper = inputstreamhelper.Helper('hls', drm='com.widevine.alpha') is_installed = is_helper.check_inputstream() self.assertTrue(is_installed, True)
def PLAY(url): global goToken global individualization global customerId global GOcustomerId global sessionId global loggedin_headers # Logging in if the user is anonymous if sessionId == '00000000-0000-0000-0000-000000000000': LOGIN() # Providing external / alternative subtitles if se == 'true': try: req = urllib2.Request( 'http://huapi.hbogo.eu/v7/Content/json/HUN/ANMO/' + cid, None, loggedin_headers) print(cid) req.add_header('User-Agent', MUA) opener = urllib2.build_opener() f = opener.open(req) jsonrsps = json.loads(f.read()) # Download the official TTML episode subtitles and convert them to SRT try: if jsonrsps['Subtitles'][0]['Code'] == Code: slink = jsonrsps['Subtitles'][0]['Url'] elif jsonrsps['Subtitles'][1]['Code'] == Code: slink = jsonrsps['Subtitles'][1]['Url'] req = urllib2.Request(slink, None, loggedin_headers) response = urllib2.urlopen(req) data = response.read() response.close() subs = re.compile( '<p[^>]+begin="([^"]+)\D(\d+)"[^>]+end="([^"]+)\D(\d+)"[^>]*>([\w\W]+?)</p>' ).findall(data) row = 0 buffer = '' for sub in subs: row = row + 1 buffer += str(row) + '\n' buffer += "%s,%03d" % (sub[0], int( sub[1])) + ' --> ' + "%s,%03d" % (sub[2], int( sub[3])) + '\n' buffer += urllib.unquote_plus(sub[4]).replace( '<br/>', '\n').replace('<br />', '\n').replace( "\r\n", "").replace("<", "<").replace( ">", ">").replace("\n ", "").strip() buffer += '\n\n' sub = 'true' with open(srtsubs_path, "w") as subfile: subfile.write(buffer) # Generates an error to exclude subtitles for any problem if sub != 'true': raise Exception() except: sub = 'false' except: sub = 'false' # Requesting an ism Manifest purchase_payload = '<Purchase xmlns="go:v7:interop" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"><AllowHighResolution>true</AllowHighResolution><ContentId>' + cid + '</ContentId><CustomerId>' + GOcustomerId + '</CustomerId><Individualization>' + individualization + '</Individualization><OperatorId>' + op_id + '</OperatorId><IsFree>false</IsFree><RequiredPlatform>COMP</RequiredPlatform><UseInteractivity>false</UseInteractivity></Purchase>' purchase_headers = { 'Accept': 'application/json, text/javascript, */*; q=0.01', 'Accept-Encoding': '', 'Accept-Language': 'en-US,en;q=0.8', 'Connection': 'keep-alive', 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8', 'GO-CustomerId': str(GOcustomerId), 'GO-requiredPlatform': 'CHBR', 'GO-SessionId': str(sessionId), 'GO-swVersion': '4.7.4', 'GO-Token': str(goToken), 'Origin': 'https://www.hbogo.hu', 'User-Agent': UA } req = urllib2.Request('https://huapi.hbogo.eu/v7/Purchase/Json/HUN/COMP', purchase_payload, purchase_headers) opener = urllib2.build_opener() f = opener.open(req) jsonrspp = json.loads(f.read()) try: if jsonrspp['ErrorMessage']: xbmcgui.Dialog().ok('Hiba', jsonrspp['ErrorMessage']) except: pass MediaUrl = jsonrspp['Purchase']['MediaUrl'] + "/Manifest" PlayerSessionId = jsonrspp['Purchase']['PlayerSessionId'] x_dt_auth_token = jsonrspp['Purchase']['AuthToken'] dt_custom_data = base64.b64encode("{\"userId\":\"" + GOcustomerId + "\",\"sessionId\":\"" + PlayerSessionId + "\",\"merchant\":\"hboeurope\"}") # Play the video xbmc.executebuiltin( 'Notification(%s, %s, %d, %s)' % (username, 'Popcorn time!', 4000, md + 'DefaultUser.png')) is_helper = inputstreamhelper.Helper('ism', drm='com.widevine.alpha') if is_helper.check_inputstream(): li = xbmcgui.ListItem(iconImage=thumbnail, thumbnailImage=thumbnail, path=MediaUrl) if (se == 'true' and sub == 'true'): # Set external subtitles if this mode is selected li.setSubtitles([srtsubs_path]) license_server = 'https://lic.drmtoday.com/license-proxy-widevine/cenc/' license_headers = 'dt-custom-data=' + dt_custom_data + '&x-dt-auth-token=' + x_dt_auth_token + '&Origin=https://www.hbogo.hu&Content-Type=' license_key = license_server + '|' + license_headers + '|R{SSM}|JBlicense' li.setProperty('inputstreamaddon', 'inputstream.adaptive') li.setProperty('inputstream.adaptive.manifest_type', 'ism') li.setProperty('inputstream.adaptive.license_type', 'com.widevine.alpha') li.setProperty('inputstream.adaptive.license_data', 'ZmtqM2xqYVNkZmFsa3Izag==') li.setProperty('inputstream.adaptive.license_key', license_key) xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, li)
def play_dirette(url, live): if live: if url == G.URL_LIVE_LA7: url_title = G.URL_BASE regex5 = 'emissioneString\s*=\s*"(.*?)"' elif url == G.URL_LIVE_LA7D: url_title = G.URL_BASE_LA7D regex5 = 'emissioneStringLa7d\s*=\s*"(.*?)"' #xbmc.log('URL TITLE-----: '+str(url_title),xbmc.LOGINFO) req = Request(url_title, headers={'user-agent': G.HEADERS_SET['user-agent']}) page = urlopen(req).read() html = page.decode() #xbmc.log('REGEX5-----: '+str(re.findall(regex5, html)),xbmc.LOGINFO) titolo_diretta = re.findall(regex5, html)[0] #xbmc.log('TITOLO DIRETTA-----: '+str(titolo_diretta),xbmc.LOGINFO) response = requests.get(url, headers={ 'user-agent': G.HEADERS_SET['user-agent'] }, verify=False).content.decode() try: preurl = re.findall('preTokenUrl = "(.+?)"', response)[0] except Exception as e: e = sys.exc_info()[0] xbmc.log('EXCEP PREURL: ' + str(e), xbmc.LOGINFO) xbmcplugin.endOfDirectory(G.PLUGIN_HANDLE, succeeded=False) return response = response.replace("\'", '"') mpdurl = re.findall('dash.+?"(.+?)"', response, re.DOTALL)[0] headersTok = { 'host': G.HEADERS_SET['host_token'], 'user-agent': G.HEADERS_SET['user-agent'], 'accept': G.HEADERS_SET['accept'], 'accept-language': G.HEADERS_SET['accept-language'], 'dnt': G.HEADERS_SET['dnt'], 'te': G.HEADERS_SET['te'], 'origin': G.HEADERS_SET['origin'], 'referer': G.HEADERS_SET['referer'], } response = requests.get(preurl, headers=headersTok, verify=False).json() preAuthToken = response['preAuthToken'] headersLic = { 'host': G.HEADERS_SET['host_license'], 'user-agent': G.HEADERS_SET['user-agent'], 'accept': G.HEADERS_SET['accept'], 'accept-language': G.HEADERS_SET['accept-language'], 'preAuthorization': preAuthToken, 'origin': G.HEADERS_SET['origin'], 'referer': G.HEADERS_SET['referer'], } preLic = '&'.join( ['%s=%s' % (name, value) for (name, value) in headersLic.items()]) #xbmc.log('LICENSE1------: '+str(preLic),xbmc.LOGINFO) tsatmp = str(int(time.time())) license_url = G.KEY_WIDEVINE + '?d=%s' % tsatmp lic_url = '%s|%s|R{SSM}|' % (license_url, preLic) #xbmc.log('LICENSE2------: '+str(lic_url),xbmc.LOGINFO) is_helper = inputstreamhelper.Helper(G.DRM_PROTOCOL, drm=G.DRM) if is_helper.check_inputstream(): listitem = xbmcgui.ListItem(offscreen=True) listitem.setPath(mpdurl) if live: #listitem.setLabel(titolo_diretta) listitem.setInfo('video', { 'plot': titolo_diretta, 'title': titolo_diretta }) listitem.setProperty( 'inputstream.adaptive.manifest_update_parameter', 'full' ) #https://github.com/xbmc/inputstream.adaptive/issues/647 listitem.setProperty("inputstream", is_helper.inputstream_addon) listitem.setProperty("inputstream.adaptive.manifest_type", G.DRM_PROTOCOL) listitem.setProperty("inputstream.adaptive.license_type", G.DRM) listitem.setProperty("inputstream.adaptive.license_key", lic_url) listitem.setProperty( "inputstream.adaptive.license_flags", "force_secure_decoder" ) #https://github.com/xbmc/inputstream.adaptive/issues/638 listitem.setMimeType('application/dash+xml') xbmcplugin.setResolvedUrl(G.PLUGIN_HANDLE, True, listitem) else: xbmcplugin.endOfDirectory(G.PLUGIN_HANDLE, succeeded=False)
def get_live_url(plugin, item_id, video_id, **kwargs): if item_id == 'fun_radio' or \ item_id == 'rtl2' or \ item_id == 'mb': if item_id == 'mb': video_json = urlquick.get( URL_LIVE_JSON % (item_id.upper()), headers={'User-Agent': web_utils.get_random_ua()}, max_age=-1) json_parser = json.loads(video_json.text) video_assets = json_parser[item_id.upper()][0]['live']['assets'] else: video_json = urlquick.get( URL_LIVE_JSON % (item_id), headers={'User-Agent': web_utils.get_random_ua()}, max_age=-1) json_parser = json.loads(video_json.text) video_assets = json_parser[item_id][0]['live']['assets'] if not video_assets: plugin.notify('INFO', plugin.localize(30716)) return False subtitle_url = '' if plugin.setting.get_boolean('active_subtitle'): for asset in video_assets: if 'subtitle_vtt' in asset["type"]: subtitle_url = asset['full_physical_path'] for asset in video_assets: if 'delta_hls_h264' in asset["type"]: item = Listitem() item.path = asset['full_physical_path'] if 'http' in subtitle_url: item.subtitles.append(subtitle_url) item.label = get_selected_item_label() item.art.update(get_selected_item_art()) item.info.update(get_selected_item_info()) return item return False else: if get_kodi_version() < 18: xbmcgui.Dialog().ok('Info', plugin.localize(30602)) return False resp_js_id = urlquick.get(URL_GET_JS_ID_API_KEY) js_id = re.compile(r'client\-(.*?)\.bundle\.js').findall( resp_js_id.text)[0] resp = urlquick.get(URL_API_KEY % js_id) api_key = re.compile(r'\"eu1.gigya.com\"\,key\:\"(.*?)\"').findall( resp.text)[0] if plugin.setting.get_string('6play.login') == '' or\ plugin.setting.get_string('6play.password') == '': xbmcgui.Dialog().ok( 'Info', plugin.localize(30604) % ('6play', 'https://www.6play.fr')) return False # Build PAYLOAD payload = { "loginID": plugin.setting.get_string('6play.login'), "password": plugin.setting.get_string('6play.password'), "apiKey": api_key, "format": "jsonp", "callback": "jsonp_3bbusffr388pem4" } # LOGIN resp2 = urlquick.post(URL_COMPTE_LOGIN, data=payload, headers={ 'User-Agent': web_utils.get_random_ua(), 'referer': 'https://www.6play.fr/connexion' }) json_parser = json.loads( resp2.text.replace('jsonp_3bbusffr388pem4(', '').replace(');', '')) if "UID" not in json_parser: plugin.notify('ERROR', '6play : ' + plugin.localize(30711)) return False account_id = json_parser["UID"] account_timestamp = json_parser["signatureTimestamp"] account_signature = json_parser["UIDSignature"] is_helper = inputstreamhelper.Helper('mpd', drm='widevine') if not is_helper.check_inputstream(): return False # Build PAYLOAD headers payload_headers = { 'x-auth-gigya-signature': account_signature, 'x-auth-gigya-signature-timestamp': account_timestamp, 'x-auth-gigya-uid': account_id, 'x-customer-name': 'm6web' } if item_id == '6ter': token_json = urlquick.get(URL_TOKEN_DRM % (account_id, 'dashcenc_%s' % '6T'), headers=payload_headers, max_age=-1) else: token_json = urlquick.get( URL_TOKEN_DRM % (account_id, 'dashcenc_%s' % item_id.upper()), headers=payload_headers, max_age=-1) token_jsonparser = json.loads(token_json.text) token = token_jsonparser["token"] if item_id == '6ter': video_json = urlquick.get( URL_LIVE_JSON % '6T', headers={'User-Agent': web_utils.get_random_ua()}, max_age=-1) json_parser = json.loads(video_json.text) video_assets = json_parser['6T'][0]['live']['assets'] else: video_json = urlquick.get( URL_LIVE_JSON % (item_id.upper()), headers={'User-Agent': web_utils.get_random_ua()}, max_age=-1) json_parser = json.loads(video_json.text) video_assets = json_parser[item_id.upper()][0]['live']['assets'] if not video_assets: plugin.notify('INFO', plugin.localize(30716)) return False subtitle_url = '' if plugin.setting.get_boolean('active_subtitle'): for asset in video_assets: if 'subtitle_vtt' in asset["type"]: subtitle_url = asset['full_physical_path'] for asset in video_assets: if 'delta_dashcenc_h264' in asset["type"]: item = Listitem() item.path = asset['full_physical_path'] if 'http' in subtitle_url: item.subtitles.append(subtitle_url) item.property['inputstreamaddon'] = 'inputstream.adaptive' item.property['inputstream.adaptive.manifest_type'] = 'mpd' item.property[ 'inputstream.adaptive.license_type'] = 'com.widevine.alpha' item.property[ 'inputstream.adaptive.license_key'] = URL_LICENCE_KEY % token item.label = get_selected_item_label() item.art.update(get_selected_item_art()) item.info.update(get_selected_item_info()) return item return False
def get_video_url(plugin, item_id, video_url, download_mode=False, **kwargs): resp = urlquick.get(video_url, headers={'User-Agent': web_utils.get_random_ua()}, max_age=-1) if len(re.compile(r'www.wat.tv/embedframe/(.*?)[\"\?]').findall(resp.text)) > 0: video_id = re.compile(r'www.wat.tv/embedframe/(.*?)[\"\?]').findall( resp.text)[0] url_wat_embed = URL_WAT_BY_ID % video_id wat_embed_html = urlquick.get( url_wat_embed, headers={'User-Agent': web_utils.get_random_ua()}, max_age=-1) stream_id = re.compile('UVID=(.*?)&').findall(wat_embed_html.text)[0] url_json = URL_VIDEO_STREAM_WAT % stream_id htlm_json = urlquick.get(url_json, headers={'User-Agent': web_utils.get_random_ua()}, max_age=-1) json_parser = json.loads(htlm_json.text) # Check DRM in the m3u8 file manifest = urlquick.get(json_parser["hls"], headers={'User-Agent': web_utils.get_random_ua()}, max_age=-1) if 'drm' in manifest: Script.notify("TEST", plugin.localize(LABELS['drm_notification']), Script.NOTIFY_INFO) return False root = os.path.dirname(json_parser["hls"]) manifest = urlquick.get(json_parser["hls"].split('&max_bitrate=')[0], headers={'User-Agent': web_utils.get_random_ua()}, max_age=-1) lines = manifest.text.splitlines() final_video_url = '' all_datas_videos_quality = [] all_datas_videos_path = [] for k in range(0, len(lines) - 1): if 'RESOLUTION=' in lines[k]: all_datas_videos_quality.append( re.compile(r'RESOLUTION=(.*?)$').findall(lines[k])[0].split(',')[0]) all_datas_videos_path.append(root + '/' + lines[k + 1]) if DESIRED_QUALITY == "DIALOG": seleted_item = xbmcgui.Dialog().select( plugin.localize(LABELS['choose_video_quality']), all_datas_videos_quality) final_video_url = all_datas_videos_path[seleted_item] elif DESIRED_QUALITY == 'BEST': # Last video in the Best for k in all_datas_videos_path: url = k final_video_url = url else: final_video_url = all_datas_videos_path[0] if download_mode: return download.download_video(final_video_url) return final_video_url else: video_id = re.compile(r'tf1.fr/embedplayer/(.*?)[\"\?]').findall( resp.text)[0] video_format = 'hls' url_json = URL_VIDEO_STREAM % (video_id, video_format) htlm_json = urlquick.get(url_json, headers={'User-Agent': web_utils.get_random_ua()}, max_age=-1) json_parser = json.loads(htlm_json.text) if json_parser['code'] >= 400: plugin.notify('ERROR', plugin.localize(30716)) return False # Check DRM in the m3u8 file manifest = urlquick.get(json_parser["url"], headers={ 'User-Agent': web_utils.get_random_ua()}, max_age=-1).text if 'drm' in manifest: if get_kodi_version() < 18: xbmcgui.Dialog().ok('Info', plugin.localize(30602)) return False else: video_format = 'dash' if video_format == 'hls': final_video_url = json_parser["url"].replace('2800000', '4000000') if download_mode: return download.download_video(final_video_url) return final_video_url else: if download_mode: xbmcgui.Dialog().ok('Info', plugin.localize(30603)) return False url_json = URL_VIDEO_STREAM % (video_id, video_format) htlm_json = urlquick.get( url_json, headers={'User-Agent': web_utils.get_random_ua()}, max_age=-1) json_parser = json.loads(htlm_json.text) is_helper = inputstreamhelper.Helper('mpd', drm='widevine') if not is_helper.check_inputstream(): return False item = Listitem() item.path = json_parser["url"] item.label = get_selected_item_label() item.art.update(get_selected_item_art()) item.info.update(get_selected_item_info()) item.property['inputstreamaddon'] = 'inputstream.adaptive' item.property['inputstream.adaptive.manifest_type'] = 'mpd' item.property[ 'inputstream.adaptive.license_type'] = 'com.widevine.alpha' item.property[ 'inputstream.adaptive.license_key'] = URL_LICENCE_KEY % video_id return item
def get_live_url(plugin, item_id, video_id, item_dict, **kwargs): resp = urlquick.get(URL_LIVE_JSON % item_id[:3]) json_parser = json.loads(resp.text) live_id = '' for live_datas in json_parser["teaser"]: if live_datas["channelName"] in LIVE_LIVE_CHANNEL_NAME[item_id]: live_id = live_datas["id"] if live_id is None: # Add Notification return False resp2 = urlquick.get(URL_INFO_VIDEO % (item_id[:3], live_id)) json_parser2 = json.loads(resp2.text) # build stream_url stream_url = '' is_drm = False for stream_datas in json_parser2["chapterList"]: if live_id in stream_datas["id"]: for stream_datas_url in stream_datas["resourceList"]: if 'drmList' in stream_datas_url: is_drm = True if is_drm: if cqu.get_kodi_version() < 18: xbmcgui.Dialog().ok('Info', plugin.localize(30602)) return False is_helper = inputstreamhelper.Helper('mpd', drm='widevine') if not is_helper.check_inputstream(): return False licence_drm_url = '' for stream_datas in json_parser2["chapterList"]: if live_id in stream_datas["id"]: for stream_datas_url in stream_datas["resourceList"]: stream_url = stream_datas_url["url"] for licence_drm_datas in stream_datas_url["drmList"]: if 'WIDEVINE' in licence_drm_datas["type"]: licence_drm_url = licence_drm_datas["licenseUrl"] item = Listitem() item.path = stream_url item.property['inputstreamaddon'] = 'inputstream.adaptive' item.property['inputstream.adaptive.manifest_type'] = 'mpd' item.property[ 'inputstream.adaptive.license_type'] = 'com.widevine.alpha' item.property[ 'inputstream.adaptive.license_key'] = licence_drm_url + '|Content-Type=&User-Agent=Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3041.0 Safari/537.36&Host=srg.live.ott.irdeto.com|R{SSM}|' if item_dict: if 'label' in item_dict: item.label = item_dict['label'] if 'info' in item_dict: item.info.update(item_dict['info']) if 'art' in item_dict: item.art.update(item_dict['art']) else: item.label = LABELS[item_id] item.art["thumb"] = "" item.art["icon"] = "" item.art["fanart"] = "" item.info["plot"] = LABELS[item_id] return item else: for stream_datas in json_parser2["chapterList"]: if live_id in stream_datas["id"]: for stream_datas_url in stream_datas["resourceList"]: if 'HD' in stream_datas_url["quality"] and \ 'mpegURL' in stream_datas_url["mimeType"]: stream_url = stream_datas_url["url"] break else: if 'mpegURL' in stream_datas_url["mimeType"]: stream_url = stream_datas_url["url"] acl_value = '/i/%s/*' % ( re.compile(r'\/i\/(.*?)\/').findall(stream_url)[0]) token_datas = urlquick.get(URL_TOKEN % acl_value, max_age=-1) token_jsonparser = json.loads(token_datas.text) token = token_jsonparser["token"]["authparams"] if '?' in stream_url: final_video_url = stream_url + '&' + token else: final_video_url = stream_url + '?' + token return final_video_url
def main(argv): """Main function for the addon """ args = model.parse(argv) # inputstream adaptive settings if hasattr(args, "mode") and args.mode == "hls": is_helper = inputstreamhelper.Helper("hls") if is_helper.check_inputstream(): xbmcaddon.Addon(id="inputstream.adaptive").openSettings() return True # get account informations username = args._addon.getSetting("crunchyroll_username") password = args._addon.getSetting("crunchyroll_password") args._session_id = args._addon.getSetting("session_id") args._auth_token = args._addon.getSetting("auth_token") args._device_id = args._addon.getSetting("device_id") if not args._device_id: char_set = "0123456789abcdefghijklmnopqrstuvwxyz0123456789" args._device_id = "".join(random.sample( char_set, 8)) + "-KODI-" + "".join(random.sample( char_set, 4)) + "-" + "".join(random.sample( char_set, 4)) + "-" + "".join(random.sample(char_set, 12)) args._addon.setSetting("device_id", args._device_id) # get subtitle language args._subtitle = args._addon.getSetting("subtitle_language") if args._subtitle == "0": args._subtitle = "enUS" elif args._subtitle == "1": args._subtitle = "enGB" elif args._subtitle == "2": args._subtitle = "esLA" elif args._subtitle == "3": args._subtitle = "esES" elif args._subtitle == "4": args._subtitle = "ptBR" elif args._subtitle == "5": args._subtitle = "ptPT" elif args._subtitle == "6": args._subtitle = "frFR" elif args._subtitle == "7": args._subtitle = "deDE" elif args._subtitle == "8": args._subtitle = "arME" elif args._subtitle == "9": args._subtitle = "itIT" elif args._subtitle == "10": args._subtitle = "ruRU" else: args._subtitle = "enUS" if not (username and password): # open addon settings view.add_item(args, {"title": args._addon.getLocalizedString(30062)}) view.endofdirectory(args) args._addon.openSettings() return False else: # login if api.start(args): # list menue xbmcplugin.setContent(int(args._argv[1]), "tvshows") check_mode(args) api.close(args) else: # login failed xbmc.log("[PLUGIN] %s: Login failed" % args._addonname, xbmc.LOGERROR) view.add_item(args, {"title": args._addon.getLocalizedString(30060)}) view.endofdirectory(args) xbmcgui.Dialog().ok(args._addonname, args._addon.getLocalizedString(30060)) return False
def get_live_url(plugin, item_id, **kwargs): if get_kodi_version() < 18: xbmcgui.Dialog().ok('Info', plugin.localize(30602)) return False is_helper = inputstreamhelper.Helper('mpd', drm='widevine') if not is_helper.check_inputstream(): return False headers = {'X-Requested-With': 'XMLHttpRequest'} resp_token = urlquick.get(URL_TOKEN_API, headers=headers, max_age=-1) session_token = resp_token.cookies['npo_session'] json_parser_token = json.loads(resp_token.text) api_token = json_parser_token['token'] resp = urlquick.get(URL_LIVE_ID % item_id, max_age=-1) video_id = '' list_media_id = re.compile(r'media-id\=\"(.*?)\"').findall(resp.text) for media_id in list_media_id: if 'LI_' in media_id: video_id = media_id # Build PAYLOAD payload = {"_token": api_token} cookies = {"npo_session": session_token} resp2 = urlquick.post(URL_TOKEN_ID % video_id, cookies=cookies, data=payload, max_age=-1) json_parser = json.loads(resp2.text) token_id = json_parser['token'] resp3 = urlquick.get(URL_STREAM % (video_id, token_id), max_age=-1) json_parser2 = json.loads(resp3.text) if "html" in json_parser2 and "Vanwege uitzendrechten is het niet mogelijk om deze uitzending buiten Nederland te bekijken." in json_parser2[ "html"]: plugin.notify('ERROR', plugin.localize(30713)) return False licence_url = json_parser2["stream"]["keySystemOptions"][0]["options"][ "licenseUrl"] licence_url_header = json_parser2["stream"]["keySystemOptions"][0][ "options"]["httpRequestHeaders"] xcdata_value = licence_url_header["x-custom-data"] item = Listitem() item.path = json_parser2["stream"]["src"] item.label = get_selected_item_label() item.art.update(get_selected_item_art()) item.info.update(get_selected_item_info()) if plugin.setting.get_boolean('active_subtitle'): item.subtitles.append(URL_SUBTITLE % video_id) item.property[INPUTSTREAM_PROP] = 'inputstream.adaptive' item.property['inputstream.adaptive.manifest_type'] = 'mpd' item.property['inputstream.adaptive.license_type'] = 'com.widevine.alpha' item.property['inputstream.adaptive.manifest_update_parameter'] = 'full' item.property[ 'inputstream.adaptive.license_key'] = licence_url + '|Content-Type=&User-Agent=Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3041.0 Safari/537.36&x-custom-data=%s|R{SSM}|' % xcdata_value return item
def get_video_url(plugin, item_id, video_id, download_mode=False, **kwargs): if get_kodi_version() < 18: xbmcgui.Dialog().ok('Info', plugin.localize(30602)) return False is_helper = inputstreamhelper.Helper('mpd', drm='widevine') if not is_helper.check_inputstream(): return False # Get info_poste ? info_poste = { 'height': 1080, 'width': 1920, 'model': 'Netscape', 'name': 'Gecko', 'os': 'Linux x86_64', 'osVersion': '5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Safari/537.36","manufacturer":"Google Inc.', 'type': 'WEB' } # Get DeviveId ? payload = { 'deviceId': 'WEB_450118664537368504183835373631080192024', 'device': info_poste, 'rememberMe': False, 'username': '', 'password': '' } resp = urlquick.post(URL_TV5MONDEPLUS_AUTH_ANONYMOUS_API, json=payload) json_parser = json.loads(resp.text) headers = { 'authorization': 'Bearer %s' % json_parser["sessionToken"], } resp2 = urlquick.get(URL_STREAM_DATAS % video_id, headers=headers) json_parser2 = json.loads(resp2.text) item = Listitem() item.path = json_parser2["formats"][0]["mediaLocator"] item.property['inputstreamaddon'] = 'inputstream.adaptive' item.property['inputstream.adaptive.manifest_type'] = 'mpd' item.property[ 'inputstream.adaptive.license_type'] = 'com.widevine.alpha' # Get Licence Key HTTP 500 - {"code":100000,"message":"An error has occurred. See logs for details."} headers2 = { 'authorization': 'Bearer %s' % json_parser2["playToken"], 'referer': 'https://www.tv5mondeplus.com/', 'user-agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Safari/537.36', 'origin': 'https://www.tv5mondeplus.com', 'accept': '*/*', 'accept-encoding': 'gzip, deflate, br', 'accept-language': 'en-US,en;q=0.9', 'sec-fetch-dest': 'empty', 'sec-fetch-mode': 'cors', 'sec-fetch-site': 'cross-site' } item.property[ 'inputstream.adaptive.license_key'] = '%s|%s|R{SSM}|' % ( json_parser2["formats"][0]["drm"]["com.widevine.alpha"]["licenseServerUrl"], urlencode(headers2)) item.label = get_selected_item_label() item.art.update(get_selected_item_art()) item.info.update(get_selected_item_info()) return item
def startplayback(args): """ plays an episode """ # api request payload = {"media_id": args.episode_id, "fields": "media.duration,media.playhead,media.stream_data"} req = api.request(args, "info", payload) # check for error if req["error"]: item = xbmcgui.ListItem(getattr(args, "title", "Title not provided")) xbmcplugin.setResolvedUrl(int(args._argv[1]), False, item) xbmcgui.Dialog().ok(args._addonname, args._addon.getLocalizedString(30064)) return False # get stream url try: url = req["data"]["stream_data"]["streams"][0]["url"] except IndexError: item = xbmcgui.ListItem(getattr(args, "title", "Title not provided")) xbmcplugin.setResolvedUrl(int(args._argv[1]), False, item) xbmcgui.Dialog().ok(args._addonname, args._addon.getLocalizedString(30064)) return False # prepare playback item = xbmcgui.ListItem(getattr(args, "title", "Title not provided"), path=url) item.setMimeType("application/vnd.apple.mpegurl") item.setContentLookup(False) # inputstream adaptive is_helper = inputstreamhelper.Helper("hls") if is_helper.check_inputstream(): item.setProperty("inputstream", "inputstream.adaptive") item.setProperty("inputstream.adaptive.manifest_type", "hls") # start playback xbmcplugin.setResolvedUrl(int(args._argv[1]), True, item) # wait for playback #xbmcgui.Dialog().notification(args._addonname, args._addon.getLocalizedString(30066), xbmcgui.NOTIFICATION_INFO) if waitForPlayback(10): # if successful wait more xbmc.sleep(3000) # start fallback if not waitForPlayback(2): # start without inputstream adaptive xbmc.log("[PLUGIN] %s: Inputstream Adaptive failed, trying directly with kodi" % args._addonname, xbmc.LOGDEBUG) item.setProperty("inputstream", "") xbmc.Player().play(url, item) # sync playtime with crunchyroll if args._addon.getSetting("sync_playtime") == "true": # wait for video to begin player = xbmc.Player() if not waitForPlayback(30): xbmc.log("[PLUGIN] %s: Timeout reached, video did not start in 30 seconds" % args._addonname, xbmc.LOGERROR) #xbmcgui.Dialog().ok(args._addonname, args._addon.getLocalizedString(30064)) return # ask if user want to continue playback resume = (100/(float(req["data"]["duration"])+1)) * int(req["data"]["playhead"]) if resume >= 5 and resume <= 90: player.pause() if xbmcgui.Dialog().yesno(args._addonname, args._addon.getLocalizedString(30065) % int(resume)): player.seekTime(float(req["data"]["playhead"]) - 5) player.pause() # update playtime at crunchyroll try: while url == player.getPlayingFile(): # wait 10 seconds xbmc.sleep(10000) if url == player.getPlayingFile(): # api request payload = {"event": "playback_status", "media_id": args.episode_id, "playhead": int(player.getTime())} try: api.request(args, "log", payload) except (ssl.SSLError, URLError): # catch timeout exception pass except RuntimeError: xbmc.log("[PLUGIN] %s: Playback aborted" % args._addonname, xbmc.LOGDEBUG)
def playVideoExtra(PID, pKEY, startoffset=None, listitem_in=None): global savedTime, totalTime, key, listitem2, url, dataEmission listitem = listitem_in data = getVideoExtra(PID) if listitem is None: listitem = xbmcgui.ListItem(infoLabels["title"], '', "DefaultVideo.png", g_thumbnail) listitem.setInfo("Video", infoLabels) listitem.setProperty("startoffset", str(startoffset)) #in second if data['url'] is None: return #xbmcgui.Dialog().ok("Oups","Le contenu n'est pas disponible pour les non abonnés EXTRA.") else: #if data['isDRM']: PROTOCOL = 'mpd' DRM = 'com.widevine.alpha' BEARER = data['widevineAuthToken'] url = data['url'] url = url.replace('(filter=2000)', '(filter=3000)') url = url.replace('(filter=3000)', '(filter=3000,format=mpd-time-csf)') is_helper = inputstreamhelper.Helper(PROTOCOL, drm=DRM) if is_helper.check_inputstream(): listitem.setProperty('path', url) listitem.setProperty('inputstreamaddon', is_helper.inputstream_addon) listitem.setProperty('inputstream.adaptive.manifest_type', PROTOCOL) listitem.setMimeType('application/dash+xml') listitem.setProperty('inputstream.adaptive.license_type', DRM) listitem.setProperty( 'inputstream.adaptive.license_key', data['widevineLicenseUrl'] + '|Authorization=' + BEARER + '|R{SSM}|') listitem.setProperty('inputstream.stream_headers', 'Authorization=' + BEARER) # play media player = None try: player = XBMCPlayer(xbmc.PLAYER_CORE_AUTO) except Exception: player = XBMCPlayer() pass print "================== URL ==================" #if ADDON.getSetting( "typeflux" ) == "RTSP": # #Replace URL to listen RTSP serveur # path = url.split("~acl=/i/", 1)[1].split("*~hmac=",1)[0] # url = "rtsp://medias-rtsp.tou.tv/vodtoutv/_definst_/mp4:" + path + "3000.mp4" player.play(url, listitem) key = data['IdMedia'] dataEmission = data['emission'] url = PID while player.is_active: try: savedTime = player.getTime() totalTime = player.getTotalTime() except: pass xbmc.sleep(100)