def extract_youtube(source): # pragma: no cover warnings.warn("This method was only temporary and will be removed in future release.", DeprecationWarning) # TODO: Remove this method now that youtube.dl works on kodi for Xbox # noinspection PyPackageRequirements import htmlement import urlquick # The Element class isn't been exposed directly by the C implementation # So the type trick is needed here if isinstance(source, type(htmlement.Etree.Element(None))): video_elem = source else: # Tempeary method to extract video url from an embeded youtube video. if source.startswith("http://") or source.startswith("https://"): source = urlquick.get(source, max_age=0).text try: video_elem = htmlement.fromstring(source) except RuntimeError: # pragma: no cover return None # Search for all types of embeded videos video_urls = [] video_urls.extend(video_elem.findall(".//iframe[@src]")) video_urls.extend(video_elem.findall(".//embed[@src]")) for url in video_urls: match = re.match(VALID_YOUTUBE_URL, url.get("src")) if match is not None: # pragma: no branch videoid = match.group(2) return u"plugin://plugin.video.youtube/play/?video_id={}".format(videoid)
def search_results(_, search_query): """ List search results :param Route _: Tools related to Route callbacks. :param search_query: The search term to find results for. """ url = url_constructor("/search/search_1018.php?q={}&query=like".format(search_query)) source = urlquick.get(url) root_elem = source.parse() for elem in root_elem.iterfind(".//li"): item = Listitem() atag = elem.find("a") item.art["thumb"] = url_constructor(atag.find("img").get("src")) # Extrac all title segments and join title = [atag.text] for i in atag: title.append(i.text) title.append(i.tail) item.label = "".join(filter(None, title)) # Extract plot plot_node = elem.find("div") plots = [plot_node.text] for node in plot_node: plots.append(node.text) plots.append(node.tail) item.info["plot"] = "".join(text.strip() for text in plots if text is not None) url = atag.get("href") item.set_callback(play_video, url=url) yield item
def root(_): """ Lists all categories and link's to 'Shows', 'MsMojo' and 'All videos'. site: http://www.watchmojo.com :param Route _: Tools related to callback. :return: A generator of listitems. """ # Add links to watchmojo youtube channels yield Listitem.youtube("UCaWd5_7JhbQBe4dknZhsHJg") # WatchMojo yield Listitem.youtube("UCMm0YNfHOCA-bvHmOBSx-ZA", label="WatchMojo UK") yield Listitem.youtube("UC3rLoj87ctEHCcS7BuvIzkQ", label="MsMojo") url = url_constructor("/") source = urlquick.get(url) root_elem = source.parse() # Parse only the show category elements menu_elem = root_elem.find(".//ul[@class='top-ul left']") for elem in menu_elem.iterfind(".//a"): url = elem.get("href") if url and elem.text and elem.text != "MsMojo": item = Listitem() item.label = elem.text item.set_callback(video_list, url=url) yield item
def recent_videos(_, url="newvideos.php"): """ :param Route _: The plugin parent object. :param unicode url: The url resource containing recent videos. """ # Fetch HTML Source url = url_constructor(url) resp = urlquick.get(url) root_elem = resp.parse("div", attrs={"id": "browse_main"}) node = root_elem.find("./div[@id='newvideos_results']")[0] for elem in node.iterfind("./tr"): if not elem.attrib: item = Listitem() item.art["thumb"] = elem.find(".//img").get("src") artist = elem[1].text track = elem[1][0][0].text item.label = "%s - %s" % (artist, track) item.info["artist"] = [artist] url = elem.find(".//a").get("href") item.context.related(related, url=url) item.set_callback(play_video, url=url) yield item # Fetch next page url next_tag = root_elem.findall("./div[@class='pagination']/a") if next_tag and next_tag[-1].text.startswith("next"): yield Listitem.next_page(url=next_tag[-1].get("href"))
def root(plugin, content_type="video"): """ :param Route plugin: The plugin parent object. :param str content_type: The type of content been listed e.g. video, music. This is passed in from kodi and we have no use for it as of yet. """ yield Listitem.recent(video_list, url="newvideos.html") yield Listitem.from_dict(top_videos, bold(plugin.localize(TOP_VIDEOS))) yield Listitem.from_dict(watching_now, bold(plugin.localize(WATCHING_NOW))) yield Listitem.search(search_videos) # Fetch HTML Source url = url_constructor("/browse.html") resp = urlquick.get(url) root_elem = resp.parse("div", attrs={"id": "primary"}) for elem in root_elem.iterfind("ul/li"): img = elem.find(".//img") item = Listitem() # The image tag contains both the image url and title item.label = img.get("alt") item.art["thumb"] = img.get("src") url = elem.find("div/a").get("href") item.set_callback(video_list, url=url) yield item # Add the video items here so that show at the end of the listing bold_text = bold(plugin.localize(VIDEO_OF_THE_DAY)) yield Listitem.from_dict(play_video, bold_text, params={"url": "/index.html"}) yield Listitem.from_dict(party_play, plugin.localize(PARTY_MODE), params={"url": "/randomizer.php"})
def root(plugin, content_type="video"): """ :param Route plugin: The plugin parent object. :param str content_type: The type of content been listed e.g. video, music. This is passed in from kodi and we have no use for it as of yet. """ yield Listitem.recent(recent_videos) yield Listitem.from_dict(top_videos, plugin.localize(TOP_VIDEOS)) yield Listitem.from_dict(watching_now, plugin.localize(WATCHING_NOW)) yield Listitem.search(video_list) # Fetch HTML Source url = url_constructor("/mobile/category.html") resp = urlquick.get(url, headers={"Cookie": "COOKIE_DEVICE=mobile"}) root_elem = resp.parse(u"ul", attrs={"id": "category_listing"}) for elem in root_elem.iterfind("li"): a_tag = elem.find("a") item = Listitem() # Set label with video count added item.label = "%s (%s)" % (a_tag.text, elem.find("span").text) item.set_callback(video_list, cat=a_tag.get("href")) yield item # Add the video items here so that show at the end of the listing yield Listitem.from_dict(play_video, plugin.localize(VIDEO_OF_THE_DAY), params={"url": "index.html"}) yield Listitem.from_dict(party_play, plugin.localize(PARTY_MODE), params={"url": "randomizer.php"})
def play_video(plugin, url): """ :param Resolver plugin: The plugin parent object. :param unicode url: The url of a video. :returns: A playable video url. :rtype: unicode """ url = url_constructor(url) html = urlquick.get(url, max_age=0) # Attemp to find url using extract_source first # video_url = plugin.extract_source(url) # if video_url: # return video_url # Attemp to find url using extract_youtube first youtube_video = plugin.extract_youtube(html.text) if youtube_video: return youtube_video # Attemp to search for flash file search_regx = 'clips.+?url:\s*\'(http://metalvideo\.com/videos.php\?vid=\S+)\'' match = re.search(search_regx, html.text) plugin.logger.debug(match) if match is not None: return match.group(1) # Attemp to search for direct file search_regx = 'file:\s+\'(\S+?)\'' match = re.search(search_regx, html.text) if match is not None: # pragma: no branch return match.group(1)
def related(_, url): """ :param Route _: The plugin parent object. :param unicode url: The url of a video. """ # Fetch HTML Source url = url_constructor(url) resp = urlquick.get(url) root_elem = resp.parse("div", attrs={"id": "bestincategory"}) for elem in root_elem.iterfind("ul/li/div"): img = elem.find(".//img") item = Listitem() # The image tag contains both the image url and title item.label = img.get("alt") item.art["thumb"] = img.get("src") # Find duration node = elem.find("span/span/span") if node is not None and "pm-label-duration" in node.get("class"): item.info["duration"] = node.text.strip() # View count item.info["count"] = elem.find("div/span/small").text.split(" ")[0].strip() url = elem.find("span/a").get("href") item.context.related(related, url=url) item.set_callback(play_video, url=url) yield item
def video_list(plugin, url): """ List all video for given url. site: http://www.watchmojo.com/shows/Top%2010 :param Route plugin: Tools related to Route callbacks. :param unicode url: The url to a list of videos. :return: A generator of listitems. """ url = url_constructor(url) source = urlquick.get(url) lbl_tags = plugin.localize(TAGS) # Parse all the video elements root_elem = source.parse() for line in root_elem.iterfind(".//div[@class='owl-carousel margin-bottom']"): for elem in line.iterfind(".//div[@class='item']"): yield extract_videos(lbl_tags, elem, "%b %d, %Y") # Add link to next page if available next_page = root_elem.find(".//div[@class='cat-next']") if next_page is not None: url = next_page.find("a").get("href") yield Listitem.next_page(url=url)
def top_videos(plugin): """:param Route plugin: The plugin parent object.""" # Fetch HTML Source plugin.cache_to_disc = True url = url_constructor("/topvideos.html") resp = urlquick.get(url) titles = [] urls = [] # Parse categories root_elem = resp.parse("select", attrs={"name": "categories"}) for group in root_elem.iterfind("optgroup"): for elem in group: urls.append(elem.get("value")) titles.append(elem.text.strip()) # Display list for Selection dialog = xbmcgui.Dialog() ret = dialog.select(plugin.localize(SELECT_TOP), titles) if ret >= 0: # Fetch HTML Source url = urls[ret] resp = urlquick.get(url) root_elem = resp.parse("div", attrs={"id": "topvideos_results"}) for elem in root_elem.iterfind(".//tr"): if not elem.attrib: item = Listitem() a_tag = elem[3][0] artist = elem[2].text item.label = "%s %s - %s" % (elem[0].text, artist, a_tag.text) item.art["thumb"] = elem.find(".//img").get("src") item.info["count"] = elem[4].text.replace(",", "") item.info["artist"] = [artist] url = a_tag.get("href") item.context.related(related, url=url) item.set_callback(play_video, url=url) yield item else: yield False
def video_list(_, url): """ :param Route _: The plugin parent object. :param unicode url: The url resource containing recent videos. """ # Fetch HTML Source url = url_constructor(url) resp = urlquick.get(url) root_elem = resp.parse("div", attrs={"class": "primary-content"}) for elem in root_elem.find("ul").iterfind("./li/div"): item = Listitem() item.art["thumb"] = elem.find(".//img").get("src") item.info["plot"] = elem.find("p").text.strip() # Find duration node = elem.find("span/span/span") if node is not None and "pm-label-duration" in node.get("class"): item.info["duration"] = node.text.strip() # View count views = elem.find("./div/span[@class='pm-video-attr-numbers']/small").text item.info["count"] = views.split(" ", 1)[0].strip() # Date of video date = elem.find(".//time[@datetime]").get("datetime") date = date.split("T", 1)[0] item.info.date(date, "%Y-%m-%d") # 2018-10-19 # Url to video & name a_tag = elem.find("h3/a") url = a_tag.get("href") item.label = a_tag.text # Extract the artist name from the title item.info["artist"] = [a_tag.text.split("-", 1)[0].strip()] item.context.related(related, url=url) item.set_callback(play_video, url=url) yield item # Fetch next page url next_tag = root_elem.find("./div[@class='pagination pagination-centered']/ul") if next_tag is not None: next_tag = next_tag.findall("li[@class='']/a") next_tag.reverse() for node in next_tag: if node.text == u"\xbb": yield Listitem.next_page(url=node.get("href"), callback=video_list) break
def related(plugin, url): """ List all related videos to selected video. site: http://www.watchmojo.com/video/id/19268/ :param Route plugin: Tools related to Route callbacks. :param unicode url: The url to a video. """ url = url_constructor(url) source = urlquick.get(url) lbl_tags = plugin.localize(TAGS) # Parse all the video elements root_elem = source.parse("div", attrs={"id": "owl-demo1"}) for elem in root_elem.iterfind(".//div[@class='item']"): yield extract_videos(lbl_tags, elem, "%B %d, %Y")
def watching_now(_): # Fetch HTML Source url = url_constructor("/index.html") resp = urlquick.get(url) root_elem = resp.parse("ul", attrs={"id": "mycarousel"}) for elem in root_elem.iterfind("li"): a_tag = elem.find(".//a[@title]") item = Listitem() # Fetch label & thumb item.label = a_tag.text item.art["thumb"] = elem.find(".//img").get("src") url = a_tag.get("href") item.context.related(related, url=url) item.set_callback(play_video, url=url) yield item
def video_list(plugin, url=None, cat=None, search_query=None): """ :param Route plugin: The plugin parent object. :param unicode url: The url resource containing lists of videos or next page. :param unicode cat: A category url e.g. Alternative, Folk Metal. :param unicode search_query: The video search term to use for searching. """ if search_query: url = url_constructor("search.php?keywords=%s&btn=Search" % search_query) elif cat: sortby = (u"date.html", u"artist.html", u"rating.html", u"views.html")[plugin.setting.get_int("sort")] base, _ = url_constructor(cat).rsplit("-", 1) url = "-".join((base, sortby)) else: url = url_constructor(url) resp = urlquick.get(url) root_elem = resp.parse("div", attrs={"id": "browse_main"}) for elem in root_elem.iterfind(u".//div[@class='video_i']"): item = Listitem() item.art["thumb"] = elem.find(".//img").get("src") # Extract url and remove first 'a' tag section # This makes it easir to extract 'artist' and 'song' name later a_tag = elem.find("a") url = a_tag.get("href") elem.remove(a_tag) # Fetch title span_tags = tuple(node.text for node in elem.findall(".//span")) item.label = "%s - %s" % span_tags item.info["artist"] = [span_tags[0]] # Add related video context item item.context.related(related, url=url) item.set_callback(play_video, url=url) yield item # Fetch next page url next_tag = root_elem.findall(".//div[@class='pagination']/a") if next_tag and next_tag[-1].text.startswith("next"): yield Listitem.next_page(url=next_tag[-1].get("href"))
def play_featured_video(plugin): """ Resolve video url. site: https://www.watchmojo.com/video/id/19268/ :param Resolver plugin: Tools related to Resolver callbacks. """ video_url = play_video(plugin, BASE_URL) resp = urlquick.get(BASE_URL) try: elem = resp.parse("div", attrs={"class": "cal_title"}) except RuntimeError: return None else: title = elem[0].text if video_url: # Using xbmcgui.ListItem just for setting plot info item = __import__("xbmcgui").ListItem(title, path=video_url) item.setInfo("video", {"title": title, "plot": title}) return item
def watching_now(_): # Fetch HTML Source url = url_constructor("/index.html") resp = urlquick.get(url, max_age=0) try: root_elem = resp.parse("ul", attrs={"id": "pm-ul-wn-videos"}) except RuntimeError: pass else: for elem in root_elem.iterfind("li/div"): img = elem.find(".//img") item = Listitem() # The image tag contains both the image url and title item.label = img.get("alt") item.art["thumb"] = img.get("src") url = elem.find("span/a").get("href") item.context.related(related, url=url) item.set_callback(play_video, url=url) yield item
def tags(plugin, url): """ List tags for a video. site: https://www.watchmojo.com/video/id/19268/ :param Route plugin: Tools related to Route callbacks. :param unicode url: The url to a video. :return: A generator of listitems. """ plugin.category = plugin.localize(TAGS) url = url_constructor(url) source = urlquick.get(url) # Parse all video tags root_elem = source.parse("div", attrs={"id": "tags"}) for elem in root_elem.iterfind("a"): item = Listitem() item.label = elem.text.title() item.set_callback(video_list, url="%s1" % elem.get("href")) yield item
def related(_, url): """ :param Route _: The plugin parent object. :param unicode url: The url of a video. """ # Fetch HTML Source url = url_constructor(url) resp = urlquick.get(url) root_elem = resp.parse("div", attrs={"id": "tabs_related"}) # Parse the xml for elem in root_elem.iterfind(u"div"): a_tag = elem.find("./a[@class='song_name']") item = Listitem() item.label = a_tag.text item.art["thumb"] = elem.find("./a/img").get("src") url = a_tag.get("href") item.context.related(related, url=url) item.set_callback(play_video, url=url) yield item
def root(plugin): """:type plugin: Route""" # Set context parameters based on default view setting if plugin.setting.get_int("defaultview") == 0: context_label = plugin.localize(LIST_AUDIO) context_type = "segment" item_type = "video" else: context_label = plugin.localize(LIST_VIDEO) context_type = "video" item_type = "segment" # Fetch HTML Source url = "https://www.sciencefriday.com/explore/" html = urlquick.get(url) # Parse for the content root_elem = html.parse("form", attrs={"class": "searchandfilter"}) sfid = root_elem.get("data-sf-form-id") # Add Youtube & Recent Content yield Listitem.youtube("UCDjGU4DP3b-eGxrsipCvoVQ") # Add Recent Videos link yield Listitem.from_dict(content_lister, plugin.localize(RECENT_VIDEOS), params={"sfid": sfid, "ctype": "video"}) # Add Recent Audio link yield Listitem.from_dict(content_lister, plugin.localize(RECENT_AUDIO), params={"sfid": sfid, "ctype": "segment"}) # List all topics for elem in root_elem.iterfind(".//option[@data-sf-cr]"): item = Listitem() item.label = elem.text # Add context item to link to the opposite content type. e.g. audio if video is default item.context.container(content_lister, context_label, topic=elem.attrib["value"], sfid=sfid, ctype=context_type) item.set_callback(content_lister, topic=elem.attrib["value"], ctype=item_type, sfid=sfid) yield item
def top_videos(plugin): """:param Route plugin: The plugin parent object.""" # Fetch HTML Source url = url_constructor("/topvideos.html") resp = urlquick.get(url) titles = [] urls = [] # Parse categories root_elem = resp.parse("select", attrs={"name": "categories"}) for group in root_elem.iterfind("optgroup[@label]"): if group.get("label").lower().startswith("by"): for node in group: urls.append(node.get("value")) titles.append(node.text.strip()) # Display list for Selection dialog = xbmcgui.Dialog() ret = dialog.select("[B]{}[/B]".format(plugin.localize(SELECT_TOP)), titles) if ret >= 0: return video_list(plugin, url=urls[ret]) else: return False
def root(_): """ Lists all categories and link's to 'Shows', 'MsMojo' and 'All videos'. site: http://www.watchmojo.com """ # Add links to watchmojo youtube channels yield Listitem.youtube("UCaWd5_7JhbQBe4dknZhsHJg") # WatchMojo yield Listitem.search(search_results) yield Listitem.youtube("UCMm0YNfHOCA-bvHmOBSx-ZA", label="WatchMojo UK") yield Listitem.youtube("UC9_eukrzdzY91jjDZm62FXQ", label="MojoTravels") yield Listitem.youtube("UC4HnC-AS714lT2TCTJ-A1zQ", label="MojoPlays") yield Listitem.youtube("UC88y_sxutS1mnoeBDroS74w", label="MojoTalks") yield Listitem.youtube("UC3rLoj87ctEHCcS7BuvIzkQ", label="MsMojo") yield Listitem.youtube("UCYJyrEdlwxUu7UwtFS6jA_Q", label="UnVeiled") source = urlquick.get(BASE_URL) root_elem = source.parse() # Find each category and fetch the image for the first video in the list for elem in root_elem.iterfind("./body/section/div[@class='line']"): # If we have a 'link' tag with class=more, then we are in the right section tag = elem.find("a[@class='more']") if tag is not None: url = tag.get("href") # Only list category entrys if url.startswith("/categories"): item = Listitem() item.label = elem.find("h2").text.strip().title() item.art["thumb"] = url_constructor(elem.find(".//img").get("src")) item.set_callback(video_list, url=url) yield item # Add link to exclusive watchmojo video yield Listitem.from_dict(video_list, "Exclusive", params={"url": "/exclusive/1"}, art={"thumb": "https://www.watchmojo.com/uploads/blipthumbs/Fi-M-Top10-Well-" "Regarded-Controversial-Films_R7D2Y7-720p30-C_480.jpg"})
def tags(plugin, url): """ List tags for a video. site: https://www.watchmojo.com/video/id/19268/ :param Route plugin: Tools related to Route callbacks. :param unicode url: The url to a video. """ plugin.category = plugin.localize(TAGS) url = url_constructor(url) source = urlquick.get(url) # Parse all video tags root_elem = source.parse("div", attrs={"id": "tags"}) for elem in root_elem.iterfind("a"): url = elem.get("href") urlparams = utils.parse_qs(url) if "q" in urlparams: search_term = urlparams["q"] item = Listitem() item.label = elem.text.title() item.set_callback(search_results, search_term) yield item
def list_videos_search(plugin, item_id, search_query, page=0, **kwargs): has_item = False while not has_item: url_search = "https://vwdlashufe-dsn.algolia.net/1/indexes/yatta_prod_contents/" resp = urlquick.get(url_search, params={ 'page': page, 'filters': "class:video", 'query': search_query }, headers=HEADERS_YATTA) json_parser = json.loads(resp.text) nb_pages = json_parser['nbPages'] for show in json_parser['hits']: item_id_found = False for channel in show['channels']: if channel['url'] == item_id: item_id_found = True break if not item_id_found: continue has_item = True title = show['title'] label = "" program_name = None if "program" in show: program_name = show['program']['label'] label += program_name + " - " # What about "teaser" and "resume"? # E.g. http://api-front.yatta.francetv.fr/standard/publish/taxonomies/france-3_plus-belle-la-vie/contents/?size=20&page=0&sort=begin_date:desc&filter=with-no-vod,only-visible if show['type'] == "extrait": label += "[extrait] " label += title headline = show['headline_title'] plot = "" if headline: plot += headline + "\n" plot += show['text'] last_publication_date = show['dates']['last_publication_date'] publication_date = time.strftime( "%Y-%m-%d", time.localtime(last_publication_date)) image_400 = "" image_1024 = "" if "image" in show: image_400 = show['image']['formats']['vignette_16x9']['urls'][ 'w:400'] image_1024 = show['image']['formats']['vignette_16x9']['urls'][ 'w:1024'] rating = None if 'rating_csa_code' in show and show['rating_csa_code']: rating = show['rating_csa_code'] # Add a dash before the numbers, instead of e.g. "TP", # to simulate the CSA logo instead of having the long description if rating.isdigit(): rating = "-" + rating item = Listitem() item.label = label item.info['title'] = label item.info['tvshowtitle'] = program_name item.art['fanart'] = URL_API(image_1024) item.art['thumb'] = URL_API(image_400) item.info.date(publication_date, "%Y-%m-%d") item.info['plot'] = plot item.info['duration'] = show['duration'] item.info['director'] = show['director'] item.info['season'] = show['season_number'] item.info['mpaa'] = rating if "episode_number" in show and show['episode_number']: item.info['mediatype'] = "episode" item.info['episode'] = show['episode_number'] actors = [] if "casting" in show and show['casting']: actors = [ actor.strip() for actor in show['casting'].split(",") ] elif "presenter" in show and show['presenter']: actors.append(show['presenter']) item.info['cast'] = actors if "characters" in show and show['characters']: characters = [ role.strip() for role in show['characters'].split(",") ] if len(actors) > 0 and len(characters) > 0: item.info['castandrole'] = list( zip_longest(actors, characters)) item.set_callback(get_video_url, item_id=item_id, id_yatta=show['id'], video_label=LABELS[item_id] + " - " + item.label, item_dict=item2dict(item)) item_post_treatment(item, is_playable=True, is_downloadable=True) yield item page = page + 1 # More videos... if page != nb_pages - 1: yield Listitem.next_page(search_query=search_query, item_id=item_id, page=page + 1)
def get_video_url(plugin, item_id, video_id, item_dict, download_mode=False, video_label=None, **kwargs): 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 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 = item_dict['label'] item.info.update(item_dict['info']) item.art.update(item_dict['art']) if plugin.setting.get_boolean('active_subtitle'): item.subtitles.append(URL_SUBTITLE % video_id) 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_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 content_lister(plugin, sfid, ctype, topic=None, page_count=1): """ :type plugin: Route :type sfid: unicode :type ctype: unicode :type topic: unicode :type page_count: int """ # Add link to Alternitve Listing if page_count == 1 and topic: params = {"_updatelisting_": True, "sfid": sfid, "topic": topic, "ctype": u"segment" if ctype == u"video" else u"video"} label = plugin.localize(LIST_AUDIO) if ctype == u"video" else plugin.localize(LIST_VIDEO) item_dict = {"label": label, "callback": content_lister, "params": params} yield Listitem.from_dict(**item_dict) # Create content url if topic: url = "https://www.sciencefriday.com/wp-admin/admin-ajax.php?action=get_results&paged=%(next)s&" \ "sfid=%(sfid)s&post_types=%(ctype)s&_sft_topic=%(topic)s" % \ {"sfid": sfid, "ctype": ctype, "topic": topic, "next": page_count} else: url = "https://www.sciencefriday.com/wp-admin/admin-ajax.php?action=get_results&paged=%(next)s&" \ "sfid=%(sfid)s&post_types=%(ctype)s" % \ {"sfid": sfid, "ctype": ctype, "next": page_count} # Fetch & parse HTML Source ishd = bool(plugin.setting.get_int("video_quality", addon_id="script.module.youtube.dl")) root_elem = urlquick.get(url).parse() # Fetch next page next_url = root_elem.find(".//a[@rel='next']") if next_url is not None: # pragma: no branch yield Listitem.next_page(sfid=sfid, ctype=ctype, page_count=page_count+1) # Parse the elements for element in root_elem.iterfind(".//article"): tag_a = element.find(".//a[@rel='bookmark']") item = Listitem() item.label = tag_a.text item.stream.hd(ishd) # Fetch plot & duration tag_p = element.findall(".//p") if tag_p and tag_p[0].get("class") == "run-time": item.info["duration"] = tag_p[0].text item.info["plot"] = tag_p[1].text elif tag_p: # pragma: no branch item.info["plot"] = tag_p[0].text # Fetch image if exists img = element.find(".//img[@data-src]") if img is not None: item.art["thumb"] = img.get("data-src") # Fetch audio/video url tag_audio = element.find(".//a[@data-audio]") if tag_audio is not None: audio_url = tag_audio.get("data-audio") item.set_callback(audio_url) else: item.set_callback(play_video, url=tag_a.get("href")) yield 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_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 + '|X-Forwarded-For=' + '2.' + str( randint(0, 15)) + '.' + str(randint(0, 255)) + '.' + str( randint(0, 255)) + '&User-Agent=' + web_utils.get_random_ua() if 'dash' in all_video_datas[0][0]: 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]: if download_mode: xbmcgui.Dialog().ok(plugin.localize(14116), plugin.localize(30603)) return False 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: headers = { 'User-Agent': web_utils.get_random_ua(), # 2.0.0.0 -> 2.16.0.255 are french IP addresses, see https://lite.ip2location.com/france-ip-address-ranges # 'X-Forwarded-For': '2.' + str(randint(0, 15)) + '.' + str(randint(0, 255)) + '.' + str(randint(0, 255)), } stream_headers = urlencode(headers) json_parser2 = json.loads( urlquick.get(url_selected, headers=headers, max_age=-1).text) resp3 = urlquick.get(json_parser2['url'], headers=headers, max_age=-1, allow_redirects=False) location_url = resp3.headers['location'] item.path = location_url item.property[ 'inputstream.adaptive.stream_headers'] = stream_headers if download_mode: return download.download_video(item.path) return item # Return info the format is not known return False
def make_requests(url, headers=False, delay=6000, max_age=-1, **kwargs): params = ChannelRequestHandler.getTokenParams(delay=delay) headers = headers or {"User-Agent": "jiotv"} return urlquick.get(url, params=params, headers=headers, max_age=max_age, raise_for_status=False, **kwargs)
def list_videos_franchise(plugin, item_id, program_url, **kwargs): if 'page=' in program_url: resp = urlquick.get(program_url + '&ApiKey=%s' % (API_KEY)) json_parser = json.loads(resp.text) for video_datas in json_parser["items"]: if 'seasonNumber' in video_datas and video_datas[ 'seasonNumber'] is not None: video_title = video_datas["title"] + " - S%sE%s" % ( str(video_datas['seasonNumber']), str(video_datas['episodeNumber'])) else: video_title = video_datas["title"] if 'header' in video_datas["images"]: video_image = URL_IMAGE % video_datas["images"]["header"]["id"] else: video_image = '' video_plot = video_datas["description"] video_id = video_datas["id"] video_duration = video_datas["duration"] date_value = video_datas['broadcastDate'].split('T')[0] item = Listitem() item.label = video_title item.art['thumb'] = item.art['landscape'] = video_image item.info['plot'] = video_plot item.info['duration'] = video_duration item.info.date(date_value, "%Y-%m-%d") item.set_callback(get_video_url, item_id=item_id, video_id=video_id) item_post_treatment(item, is_playable=True, is_downloadable=False) yield item if 'next' in json_parser["_links"]: yield Listitem.next_page( item_id=item_id, program_url=json_parser["_links"]['next']['href']) else: resp = urlquick.get( program_url.replace('/router', '') + '?ApiKey=%s' % API_KEY) json_parser = json.loads(resp.text) for video_datas in json_parser["components"][2]["data"]["items"]: try: video_title = str(video_datas["title"] + " - S%sE%s" % (str(video_datas['seasonNumber']), str(video_datas['episodeNumber']))) except Exception: video_title = str(video_datas["title"]) if 'header' in video_datas["images"]: video_image = URL_IMAGE % video_datas["images"]["header"]["id"] else: video_image = '' video_plot = video_datas["description"] video_id = video_datas["id"] video_duration = video_datas["duration"] date_value = video_datas['broadcastDate'].split('T')[0] item = Listitem() item.label = video_title item.art['thumb'] = item.art['landscape'] = video_image item.info['plot'] = video_plot item.info['duration'] = video_duration item.info.date(date_value, "%Y-%m-%d") item.set_callback(get_video_url, item_id=item_id, video_id=video_id) item_post_treatment(item, is_playable=True, is_downloadable=False) yield item if 'next' in json_parser["components"][2]["data"]["_links"]: yield Listitem.next_page(item_id=item_id, program_url=json_parser["components"][2] ["data"]["_links"]['next']['href'])
def get_live_url(plugin, item_id, video_id, **kwargs): resp = urlquick.get(URL_LIVE, headers={'User-Agent': web_utils.get_random_ua()}, max_age=-1) return re.compile(r'x-mpegurl" src="(.*?)"').findall(resp.text)[0]
def list_videos_programs(plugin, item_id, next_url, page, **kwargs): resp = urlquick.get(next_url) program_id_values = re.compile(r'\/program\.(.*?)\/prepare').findall( resp.text) if len(program_id_values) > 0: if DESIRED_LANGUAGE == 'FR': resp2 = urlquick.get( eval('URL_ROOT_%s' % DESIRED_LANGUAGE) + '/listing/program.%s/prepare/idi-listing/10/%s' % (program_id_values[0], page)) root = resp2.parse("div", attrs={"data-role": "content"}) for video_datas in root.iterfind(".//div[@data-role='item']"): video_title = video_datas.find( ".//span[@class='st-idi-episode-card__title']").text.strip( ) video_image_datas = video_datas.find( ".//span[@class='st-idi-episode-card__image']").get( 'style') video_image = re.compile(r'url\((.*?)\)').findall( video_image_datas)[0] video_url = video_datas.find('.//a').get('href') video_plot = video_datas.find( ".//span[@class='st-idi-episode-card__summary']" ).text.strip() item = Listitem() item.label = video_title item.art['thumb'] = item.art['landscape'] = video_image item.info['plot'] = video_plot item.set_callback(get_video_url, item_id=item_id, video_url=video_url) item_post_treatment(item, is_playable=True, is_downloadable=True) yield item elif DESIRED_LANGUAGE == 'EN': resp2 = urlquick.get( eval('URL_ROOT_%s' % DESIRED_LANGUAGE) + '/listing/program.%s/prepare/latestepisodes/10/%s' % (program_id_values[0], page)) try: root = resp2.parse( "ul", attrs={"class": "card-rows js-listing__list"}) except Exception: root = None if root is not None: for video_datas in root.iterfind(".//li"): video_title = video_datas.find(".//img").get('alt') video_image = video_datas.find(".//img").get('data-src') video_url = eval('URL_ROOT_%s' % DESIRED_LANGUAGE ) + video_datas.find('.//a').get('href') video_plot = video_datas.find( ".//div[@class='card__summary ']").text.strip() item = Listitem() item.label = video_title item.art['thumb'] = item.art['landscape'] = video_image item.info['plot'] = video_plot item.set_callback(get_video_url, item_id=item_id, video_url=video_url) item_post_treatment(item, is_playable=True, is_downloadable=True) yield item yield Listitem.next_page(item_id=item_id, next_url=next_url, page=str(int(page) + 1)) else: if DESIRED_LANGUAGE == 'FR': root = resp.parse( "ul", attrs={"class": "telecast-list js-listing__list"}) for video_datas in root.iterfind(".//li"): video_title = video_datas.find('.//img').get('alt') video_image = video_datas.find('.//img').get('data-src') video_url = eval( 'URL_ROOT_%s' % DESIRED_LANGUAGE) + video_datas.find('.//a').get('href') video_plot = video_datas.find( ".//p[@class='card__summary ']").text.strip() item = Listitem() item.label = video_title item.art['thumb'] = item.art['landscape'] = video_image item.info['plot'] = video_plot item.set_callback(get_video_url, item_id=item_id, video_url=video_url) item_post_treatment(item, is_playable=True, is_downloadable=True) yield item elif DESIRED_LANGUAGE == 'EN': root = resp.parse("ul", attrs={"class": "card-rows js-listing__list"}) for video_datas in root.iterfind(".//li"): video_title = video_datas.find('.//img').get('alt') video_image = video_datas.find('.//img').get('data-src') video_url = eval( 'URL_ROOT_%s' % DESIRED_LANGUAGE) + video_datas.find('.//a').get('href') video_plot = video_datas.find( ".//div[@class='card__summary ']").text.strip() item = Listitem() item.label = video_title item.art['thumb'] = item.art['landscape'] = video_image item.info['plot'] = video_plot item.set_callback(get_video_url, item_id=item_id, video_url=video_url) item_post_treatment(item, is_playable=True, is_downloadable=True) yield item
def get_live_url(plugin, item_id, video_id, item_dict): resp = urlquick.get(URL_LIVE, max_age=-1) return re.compile(r'var vS \= \'(.*?)\'').findall(resp.text)[0]
def get_live_url(plugin, item_id, video_id, **kwargs): resp = urlquick.get(URL_LIVE, max_age=-1) return re.compile(r'source src\=\"(.*?)\"').findall(resp.text)[0]
def list_programs(plugin, item_id, next_url, **kwargs): resp = urlquick.get(next_url) json_parser = json.loads(resp.text) if 'strates' in json_parser: program_title = json_parser['currentPage']['displayName'] for strate in json_parser["strates"]: if strate["type"] == "contentRow" or strate["type"] == "contentGrid": strate_title = program_title + ' - ' + strate["title"] item = Listitem() item.label = strate_title item.set_callback( list_sub_programs, item_id=item_id, next_url=next_url, strate_title=strate_title) item_post_treatment(item) yield item elif 'episodes' in json_parser: program_title = json_parser['currentPage']['displayName'] for video_datas in json_parser["episodes"]['contents']: video_title = program_title + ' - ' + video_datas['title'] video_image = video_datas['URLImage'] video_plot = '' if 'summary' in video_datas: video_plot = video_datas['summary'] if 'contentAvailability' in video_datas: video_url = video_datas["contentAvailability"]["availabilities"]["stream"]["URLMedias"] else: video_url = video_datas["URLMedias"] item = Listitem() item.label = video_title item.art['thumb'] = item.art['landscape'] = video_image item.info['plot'] = video_plot item.set_callback( get_video_url, item_id=item_id, next_url=video_url) item_post_treatment(item, is_playable=True, is_downloadable=True) yield item if json_parser["episodes"]["paging"]["hasNextPage"]: yield Listitem.next_page(item_id=item_id, next_url=json_parser["episodes"]["paging"]["URLPage"]) elif 'detail' in json_parser: if 'seasons' in json_parser['detail']: for seasons_datas in json_parser['detail']['seasons']: if 'seasonNumber' in seasons_datas: season_title = seasons_datas['onClick']['displayName'] + \ ' (Saison ' + str(seasons_datas["seasonNumber"]) + ')' else: season_title = seasons_datas['onClick']['displayName'] season_url = seasons_datas['onClick']['URLPage'] item = Listitem() item.label = season_title item.set_callback( list_videos, item_id=item_id, next_url=season_url) item_post_treatment(item) yield item else: # Case just one video program_title = json_parser['currentPage']['displayName'] video_datas = json_parser['detail']['informations'] if 'subtitle' in video_datas: video_title = program_title + ' - ' + video_datas['title'] + ' - ' + video_datas['subtitle'] else: video_title = program_title + ' - ' + video_datas['title'] video_image = video_datas['URLImage'] video_plot = '' if 'summary' in video_datas: video_plot = video_datas['summary'] if 'contentAvailability' in video_datas: video_url = video_datas["contentAvailability"]["availabilities"]["stream"]["URLMedias"] else: video_url = video_datas["URLMedias"] item = Listitem() item.label = video_title item.art['thumb'] = item.art['landscape'] = video_image item.info['plot'] = video_plot item.set_callback( get_video_url, item_id=item_id, next_url=video_url) item_post_treatment(item, is_playable=True, is_downloadable=True) yield item elif 'contents' in json_parser: for content_datas in json_parser['contents']: if content_datas["type"] != 'article': if 'subtitle' in content_datas: content_title = content_datas['title'] + \ ' - ' + content_datas['subtitle'] else: content_title = content_datas['title'] content_image = content_datas['URLImage'] content_url = content_datas['onClick']['URLPage'] item = Listitem() item.label = content_title item.art['thumb'] = item.art['landscape'] = content_image item.set_callback( list_programs, item_id=item_id, next_url=content_url) item_post_treatment(item) yield item
def list_videos_program(plugin, item_id, next_url, page, **kwargs): # Cas emission (2 cas) (-0) ou (sans -0) # 1ère page http://www.lcp.fr/emissions/evenements/replay-0 # (url départ => http://www.lcp.fr/emissions/evenements-0) # 1ère page http://www.lcp.fr/emissions/evenements/replay-0?page=1 # ainsi de suite # 1ère page : http://www.lcp.fr/emissions/en-voiture-citoyens/replay # (url départ => http://www.lcp.fr/emissions/en-voiture-citoyens) # 2ème page : # http://www.lcp.fr/emissions/en-voiture-citoyens/replay?page=1 # ainsi de suite # TODO fix some cases http://www.lcp.fr/emissions/questions-au-gouvernement/replay-2 http://www.lcp.fr/emissions/questions-au-gouvernement-2 if page == '0' and '-0' not in next_url: video_program_url = next_url + '/replay' elif int(page) > 0 and '-0' not in next_url: video_program_url = next_url + '/replay?page=' + page elif page == '0' and '-0' in next_url: video_program_url = next_url[:-2] + '/replay-0' elif int(page) > 0 and '-0' in next_url: video_program_url = next_url[:-2] + '/replay-0?page=' + page resp = urlquick.get(video_program_url) root = resp.parse() for video_datas in root.iterfind( ".//div[@class='col-md-3 col-sm-6 col-xs-12']"): video_title = video_datas.find( ".//span[@class='rdf-meta element-hidden']").get('content') video_image = video_datas.find('.//img').get('src') video_duration = int( video_datas.find(".//div[@class='duration']").find('.//div').find( './/span').text) * 60 video_url = URL_ROOT + video_datas.find('.//a').get('href') date_value = video_datas.find(".//span[@class='date']").text date = date_value.split(' ') day = date[0] try: month = CORRECT_MONTH[date[1]] except Exception: month = '00' year = date[2] date_value = year + '-' + month + '-' + day item = Listitem() item.label = video_title item.art['thumb'] = video_image item.info['duration'] = video_duration item.info.date(date_value, '%Y-%m-%d') item.set_callback(get_video_url, item_id=item_id, video_label=LABELS[item_id] + ' - ' + item.label, video_url=video_url) item_post_treatment(item, is_playable=True, is_downloadable=True) yield item yield Listitem.next_page(item_id=item_id, next_url=next_url, page=str(int(page) + 1))
def get_live_url(plugin, item_id, video_id, item_dict, **kwargs): resp = urlquick.get(URL_LIVE) live_id = re.compile(r'dailymotion.com/embed/video/(.*?)[\?\"]').findall( resp.text)[0] return resolver_proxy.get_stream_dailymotion(plugin, live_id, False)
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_live_url(plugin, item_id, video_id, **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 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}|' item.label = get_selected_item_label() item.art.update(get_selected_item_art()) item.info.update(get_selected_item_info()) 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 get_video_url(plugin, item_id, program_id, download_mode=False, video_label=None, **kwargs): if 'www.wat.tv/embedframe' in program_id: url = 'http:' + program_id elif "http" not in program_id: if program_id[0] == '/': program_id = program_id[1:] url = URL_ROOT(program_id) else: url = program_id video_html = urlquick.get(url).text if 'www.wat.tv/embedframe' in program_id: video_id = re.compile('UVID=(.*?)&').findall(video_html)[0] elif item_id == 'lci': video_id = re.compile(r'data-videoid="(.*?)"').findall(video_html)[0] else: root = video_html.parse() iframe_player = root.find(".//div[@class='iframe_player']") if iframe_player is not None: video_id = iframe_player.get('data-watid') else: video_id = re.compile( r'www\.tf1\.fr\/embedplayer\/(.*?)\"').findall(video_html)[0] url_json = URL_VIDEO_STREAM % video_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).text 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) final_video_url = '' lines = manifest.text.splitlines() 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]) 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, video_label) return final_video_url
def list_videos(plugin, item_id, program_id, sub_category_id, **kwargs): url = '' if sub_category_id is None: url = URL_VIDEOS2 % program_id else: url = URL_VIDEOS % (program_id, sub_category_id) resp = urlquick.get(url, headers={ 'User-Agent': web_utils.get_random_ua(), 'x-customer-name': 'rtlbe' }) json_parser = json.loads(resp.text) # TO DO Playlist More one 'clips' at_least_one_item = False for video in json_parser: video_id = str(video['id']) title = video['title'] duration = video['clips'][0]['duration'] description = '' if 'description' in video: description = video['description'] try: aired = video['clips'][0]['product']['last_diffusion'] aired = aired aired = aired[:10] # year = aired[:4] # date : string (%d.%m.%Y / 01.01.2009) # aired : string (2008-12-07) # day = aired.split('-')[2] # mounth = aired.split('-')[1] # year = aired.split('-')[0] # date = '.'.join((day, mounth, year)) except Exception: aired = '' # year = '' # date = '' img = '' program_imgs = video['clips'][0]['images'] program_img = '' for img in program_imgs: if img['role'] == 'vignette': external_key = img['external_key'] program_img = URL_IMG % (external_key) item = Listitem() at_least_one_item = True item.label = title item.info['plot'] = description item.info['duration'] = duration item.art['thumb'] = item.art['landscape'] = program_img item.art['fanart'] = program_img try: item.info.date(aired, '%Y-%m-%d') except Exception: pass is_downloadable = False if get_kodi_version() < 18: is_downloadable = True item.set_callback(get_video_url, item_id=item_id, video_id=video_id) item_post_treatment(item, is_playable=True, is_downloadable=is_downloadable) yield item if not at_least_one_item: plugin.notify(plugin.localize(30718), '') yield False
def get_live_url(plugin, item_id, video_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 = re.compile(r'media-id\=\"(.*?)\"').findall(resp.text)[0] # 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['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_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: video_json = urlquick.get(URL_JSON_VIDEO % video_id, headers={ 'User-Agent': web_utils.get_random_ua(), 'x-customer-name': 'rtlbe' }, 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(30709), all_datas_videos_quality) if seleted_item == -1: return False final_video_url = 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: video_json = urlquick.get(URL_JSON_VIDEO % video_id, headers={ 'User-Agent': web_utils.get_random_ua(), 'x-customer-name': 'rtlbe' }, 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 None 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'login.rtl.be\"\,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": "gigya.callback" } # 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('gigya.callback(', '').replace(');', '')) if "UID" not in json_parser: plugin.notify('ERROR', 'RTLPlay (BE) : ' + plugin.localize(30711)) return None 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' } 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"] 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 _buildItem(self, item): context = [] if item.get("assetType") in ["CHANNEL", "GENRE", "GAME", "LANGUAGE", "SHOW", "SEASON"]: if item.get("assetType", "") in ["SHOW"] or item.get("pageType") in ["HERO_LANDING_PAGE", "NAVIGATION_LANDING_PAGE"]: callback = Route.ref("/resources/lib/main:menu_list") else: callback = Route.ref("/resources/lib/main:tray_list") params = {"url": item.get("uri")} else: if item.get("isSubTagged"): with PersistentDict("userdata.pickle") as db: subtag = deep_get(dict(db), "udata.subscriptions.in") if subtag: subtag = list(subtag.keys())[0] Script.log("Using subtag from subscription: %s" % subtag, lvl=Script.DEBUG) else: resp = urlquick.get( item.get("uri"), headers=BASE_HEADERS).json() item = deep_get(resp, "body.results.item") if item.get("features", [{}])[0].get("subType"): subtag = item.get("features", [{}])[ 0].get("subType") Script.log("Using subtag %s" % subtag, lvl=Script.DEBUG) else: subtag = "HotstarPremium" Script.log("No subType found.Using subtag %s as default" % subtag, lvl=Script.DEBUG) callback = Resolver.ref("/resources/lib/main:play_vod") params = { "contentId": item.get("contentId"), "subtag": item.get("isSubTagged") and "subs-tag:%s|" % subtag, "label": item.get("title"), "drm": "com.widevine.alpha" if item.get("encrypted") or item.get("clipType", "") == "LIVE" else False, "partner": "com.jio.jioplay.tv" if item.get("clipType", "") == "LIVE" else None } context.extend([("Select Playback", "PlayMedia(plugin://plugin.video.botallen.hotstar/resources/lib/main/play_vod/?_pickle_=%s)" % hexlify(dumps(dict({"ask": True}, **params))).decode("ascii"))]) if len(item.get("langObjs", [])) > 1: context.extend(map(lambda x: ("Play in %s" % x.get("name"), "PlayMedia(plugin://plugin.video.botallen.hotstar/resources/lib/main/play_vod/?_pickle_=%s)" % hexlify(dumps(dict({"lang": x.get("iso3code")}, **params))).decode("ascii")), item.get("langObjs", []))) label = item.get("title") if item.get("clipType", "") == "LIVE": label += " - [COLOR red]LIVE[/COLOR]" elif item.get("assetType") == "SEASON": label = "Season {0} ({1})".format( item.get("seasonNo"), item.get("episodeCnt")) props = {"IsPlayable": False} if item.get("watched"): props["ResumeTime"] = item.get( "watched", 0) * item.get("duration", 0) props["TotalTime"] = item.get("duration", 0) return { "label": label, "art": { "icon": IMG_THUMB_H_URL % deep_get(item, "images.h"), "thumb": IMG_THUMB_H_URL % deep_get(item, "images.h"), "fanart": IMG_FANART_H_URL % deep_get(item, "images.h"), "poster": IMG_POSTER_V_URL % ((deep_get(item, "images.v") or deep_get(item, "imageSets.DARK_THEME.v") or deep_get(item, "images.h"))) }, "info": { "genre": item.get("genre"), "year": item.get("year"), "episode": item.get("episodeNo") or item.get("episodeCnt"), "season": item.get("seasonNo") or item.get("seasonCnt"), "mpaa": item.get("parentalRatingName"), "plot": item.get("description"), "title": label, "sorttitle": item.get("shortTitle"), "duration": item.get("duration"), "studio": item.get("cpDisplayName"), "premiered": item.get("broadCastDate") and datetime.fromtimestamp(item.get("broadCastDate")).strftime("%Y-%m-%d"), "path": "", "trailer": "", "dateadded": item.get("broadCastDate") and datetime.fromtimestamp(item.get("broadCastDate")).strftime("%Y-%m-%d %H:%M:%S"), "mediatype": MEDIA_TYPE.get(item.get("assetType")) }, "properties": props, # TODO: Get Stream Info # "stream": { # # "video_codec": "h264", # "width": "1920", # "height": "1080", # # "audio_codec": "aac" # }, "callback": callback, "context": context, "params": params }
def get_live_url(plugin, item_id, video_id, **kwargs): 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'login.rtl.be\"\,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": "gigya.callback" } # 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('gigya.callback(', '').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 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_live_url(plugin, item_id, video_id, item_dict): if item_id == 'viavosges': live_html = urlquick.get( URL_LIVE_VIAVOSGES, headers={'User-Agent': web_utils.get_random_ua}, max_age=-1) live_soup = bs(live_html.text, 'html.parser') url_live_datas = URL_ROOT_VIAVOSGES + live_soup.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 = item_dict['label'] item.info.update(item_dict['info']) item.art.update(item_dict['art']) 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) live_soup = bs(live_html.text, 'html.parser') list_lives_datas = live_soup.find_all('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_url, download_mode=False, **kwargs): resp = urlquick.get(video_url) video_id = re.compile(r"youtube\.com\/embed\/(.*?)\"").findall( resp.text)[0] return resolver_proxy.get_stream_youtube(plugin, video_id, download_mode)
def get_token(item_id): """Get session token""" resp = urlquick.get(URL_TOKEN % item_id) json_parser = json.loads(resp.text) return json_parser['session']['token']
def get_live_url(plugin, item_id, video_id, **kwargs): resp = urlquick.get(URL_ROOT) live_id = re.compile(r"youtube\.com\/embed\/(.*?)\"").findall(resp.text)[0] return resolver_proxy.get_stream_youtube(plugin, live_id, False)
def get_video_url(plugin, item_id, video_id, item_dict=None, download_mode=False, video_label=None, **kwargs): 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 cqu.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, video_label) 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 = item_dict['label'] item.info.update(item_dict['info']) item.art.update(item_dict['art']) 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 list_videos(plugin, item_id, season_url, **kwargs): if 'api/context' in season_url: resp = urlquick.get(season_url) json_parser = json.loads(resp.text) for video_datas in json_parser['items']: video_title = video_datas['meta']['header'][ 'title'] video_image = video_datas['media']['image']['url'] video_plot = video_datas['meta']['description'] # TODO add duration / date video_url = URL_ROOT + video_datas['url'] item = Listitem() item.label = video_title item.art['thumb'] = item.art['landscape'] = video_image item.info['plot'] = video_plot item.set_callback( get_video_url, item_id=item_id, video_url=video_url) item_post_treatment( item, is_playable=True, is_downloadable=True) yield item if json_parser['loadMore'] is not None: new_season_url = URL_ROOT + json_parser['loadMore']['url'] yield Listitem.next_page(item_id=item_id, season_url=new_season_url) else: resp = urlquick.get(season_url) json_value = re.compile(r'window\.__DATA__ \= (.*?)\}\;').findall( resp.text)[0] json_parser = json.loads(json_value + '}') for main_contents_datas in json_parser['children']: if 'MainContainer' in main_contents_datas['type']: for video_child in main_contents_datas['children']: if video_child['type'] is not None: if 'LineList' in video_child['type']: video_props = video_child['props'] if 'video-guide' in video_props['type']: for video_datas in video_props['items']: video_title = video_datas['meta']['header'][ 'title'] video_image = video_datas['media']['image']['url'] video_plot = video_datas['meta']['description'] # TODO add duration / date video_url = URL_ROOT + video_datas['url'] item = Listitem() item.label = video_title item.art['thumb'] = item.art['landscape'] = video_image item.info['plot'] = video_plot item.set_callback( get_video_url, item_id=item_id, video_url=video_url) item_post_treatment( item, is_playable=True, is_downloadable=True) yield item if 'loadMore' in video_props: new_season_url = URL_ROOT + video_props['loadMore']['url'] yield Listitem.next_page( item_id=item_id, season_url=new_season_url)
def list_videos_emissions_2(plugin, item_id, page, show_url, last_page, **kwargs): resp = urlquick.get(show_url + '?page=%s' % page) root = resp.parse() if root.find(".//section[@class='media-meta-list by2 j_w']") is not None: root_episodes = root.find( ".//section[@class='media-meta-list by2 j_w']") episodes = root_episodes.findall(".//figure[@class='media-meta-fig']") else: episodes = root.findall(".//figure[@class='media-meta-fig']") for episode in episodes: item = Listitem() if episode.find('.//h3') is not None: video_title = episode.find('.//h3').find('.//span').find( './/a').find('.//strong').text.strip() + ' - ' + episode.find( './/h3').find('.//span').find('.//a').find( './/strong').tail.strip() else: if episode.find('.//h2/span/a/strong') is not None: video_title = episode.find('.//h2/span/a/strong').text.strip() \ + ' - ' + episode.find('.//h2/span/a/strong').tail.strip() elif episode.find('.//h2/span/span') is not None: video_title = episode.find('.//h2/span/span').text.strip() elif episode.find('.//h2/span/a') is not None: video_title = episode.find('.//h2/span/a').text.strip() else: video_title = '' item.label = video_title if episode.find(".//a") is not None: video_urls_datas = episode.findall(".//a") video_url = '' for video_url_datas in video_urls_datas: if 'program' not in video_url_datas.get('href'): video_url = URL_ROOT + video_url_datas.get('href') else: # TODO: ↪ Root menu (1) ➡ Websites (3) ➡ Allociné (1) ➡ Les émissions (1) ➡ Stars (6) ➡ Clips musicaux (3) ➡ # Les videos (1) ➡ [B]Next page 2[/B] continue for plot_value in episode.find( ".//div[@class='media-meta-figcaption-inner']").findall( './/p'): item.info['plot'] = plot_value.text.strip() if episode.find('.//meta') is not None: item.art['thumb'] = item.art['landscape'] = episode.find('.//meta').get('content') else: if episode.find('.//img').get('data-attr') is not None: image_json_parser = json.loads( episode.find('.//img').get('data-attr')) item.art['thumb'] = item.art['landscape'] = image_json_parser['src'] else: item.art['thumb'] = item.art['landscape'] = episode.find('.//img').get('src') item.set_callback(get_video_url, item_id=item_id, video_url=video_url) item_post_treatment(item, is_playable=True, is_downloadable=True) yield item # More videos... yield Listitem.next_page(item_id=item_id, page=page + 1, last_page=last_page, show_url=show_url)
def get_live_url(plugin, item_id, video_id, **kwargs): resp = urlquick.get(URL_LIVE) json_parser = json.loads(resp.text) return json_parser["url"]
def get_video_url(plugin, item_id, next_url, download_mode=False, **kwargs): if 'tokenCMS' 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 (not a good device ID => TODO find the good one to fix to get licence key) 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_first = 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': device_id_first, '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"] device_id = json_token_parser["response"]["userData"]["deviceId"].split(':')[0] video_id = next_url.split('/')[-1].split('.json')[0] 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 = '' if 'available' not in value_datas_jsonparser: # Some videos required an account # Get error return False is_video_drm = True for stream_datas in value_datas_jsonparser["available"]: if 'stream' in stream_datas['distTechnology']: if 'DRM' not 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'] is_video_drm = False if is_video_drm: for stream_datas in value_datas_jsonparser["available"]: if 'stream' in stream_datas['distTechnology']: 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) subtitle_url = '' item = Listitem() if 'VM' in jsonparser_real_stream_datas: item.path = jsonparser_real_stream_datas["VM"][0]["media"][0]["distribURL"] + '/manifest' if plugin.setting.get_boolean('active_subtitle'): for asset in jsonparser_real_stream_datas["VM"][0]["files"]: if 'vtt' in asset["mimeType"]: subtitle_url = asset['distribURL'] else: item.path = jsonparser_real_stream_datas["VF"][0]["media"][0]["distribURL"] + '/manifest' if plugin.setting.get_boolean('active_subtitle'): for asset in jsonparser_real_stream_datas["VF"][0]["files"]: if 'vtt' in asset["mimeType"]: subtitle_url = asset['distribURL'] 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' if 'http' in subtitle_url: item.subtitles.append(subtitle_url) if 'Widevine' in drmType_value: # DRM Message (TODO to find a way to get licence key) Script.notify("INFO", plugin.localize(30702), Script.NOTIFY_INFO) return False item.property['inputstream.adaptive.license_type'] = 'com.widevine.alpha' 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'] + '?drmConfig=mkpl::false' + '|%s|R{SSM}|' % urlencode(headers2) return item 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 get_brightcove_policy_key(data_account, data_player): """Get policy key""" file_js = urlquick.get(URL_BRIGHTCOVE_POLICY_KEY % (data_account, data_player)) return re.compile('policyKey:"(.+?)"').findall(file_js.text)[0]