def play_video(params): lutil.log("esa.play " + repr(params)) buffer_link = lutil.carga_web(params.get("url")) if language != 'en': pattern_lang = '<a href="([^\(]*?\(lang\)/%s)"' % language video_link = lutil.find_first(buffer_link, pattern_lang) if video_link: lang_url = '%s%s' % (root_url, video_link) lutil.log( "esa.play: We have found this alt video URL for '%s' language: '%s'" % (language, lang_url)) buffer_link = lutil.carga_web(lang_url) pattern_video = "file[']?: '(http[^']*?)'" video_url = lutil.find_first(buffer_link, pattern_video) if video_url: try: lutil.log( "esa.play: We have found this video: '%s' and let's going to play it!" % video_url) return lutil.play_resolved_url(pluginhandle=pluginhandle, url=video_url) except: lutil.log( 'esa.play ERROR: we cannot reproduce this video URL: "%s"' % video_url) return lutil.showWarning(translation(30012)) lutil.log( 'esa.play ERROR: we cannot play the video from this source yet: "%s"' % params.get("url")) return lutil.showWarning(translation(30011))
def main_list(params): lutil.log("tv5monde.main_list "+repr(params)) # Loads the list of videos of the selected category based on the json object retrieved from the server. buffer_json = lutil.get_json(params.get("url")) pattern_videos = '<a title="([^"]+)" href="/video/([^/]+)/[^"]+"> <img src="([^"]+)" .*?<div class="bookmark" id="book_([0-9]+)">' videolist = lutil.find_multiple(buffer_json['content'], pattern_videos) for title, day, thumbnail, videoid in videolist: video_url = 'http://www.tv5mondeplus.com/video-xml/get/%s' % videoid title = title.replace('"', '"') lutil.log('videolist: URL: "%s" Descripcion: "%s" Date: "%s" Thumbnail: "%s"' % (video_url, title, day, thumbnail)) plot = title lutil.addLink(action="play_video", title='%s (%s)' % (title, day), plot=plot, url=video_url, thumbnail=thumbnail) if buffer_json['pager'] is not None: pattern_page = 'pg=([0-9]+)' pattern_total = '<ul class="pager" total="([0-9]+)"' pattern_genre = 'sort=([0-9]+)' last_page = int(lutil.find_first(buffer_json['pager'], pattern_total)) - 1 next_page = int(lutil.find_first(params.get("url"), pattern_page)) + 1 if last_page != next_page: genre = lutil.find_first(params.get("url"), pattern_genre) next_page_url = 'http://www.tv5mondeplus.com/get/videos?pg=%s&type=genre&sort=%s&loadpg=false&order=date' % (next_page, genre) lutil.log('next_page=%s last_page=%s next_page_url="%s"' % (next_page, last_page, next_page_url)) lutil.addDir(action="main_list", title=">> %s" % translation(30010), url=next_page_url) lutil.close_dir(pluginhandle)
def main_list(params): lutil.log("eso.main_list "+repr(params)) # Loads the web page from ESO with the video list. page_url = params.get("url") reset_cache = params.get("reset_cache") genre = params.get("genre") array_index = 0 if eso_url in page_url else 1 root_url = (eso_url, space_url)[array_index] buffer_web = lutil.carga_web(page_url) # Extract video items from the html content pattern_nextpage = '<a href="([^"]*?)">Next</a>' pattern_prevpage = '<a href="([^"]*?)">Previous</a>' pattern_lastpage = '<a href="[^"]*?">([0-9]+)</a>' pattern_pagenum = '/([0-9]+)/' pattern_videos = ('</span><img src="([^"]+)" class="[^"]+" alt="([^"]+)">.*?<a href="(/public/videos/[^"]*?)">', '</span><img src="([^"]+)" class="[^"]+" alt="([^"]+)">.*?<a href="(/videos/[^"]*?)">')[array_index] lutil.set_content_list(pluginhandle, 'tvshows') lutil.set_plugin_category(pluginhandle, genre) # We must setup the previous page entry from the second page onwards. prev_page_url = lutil.find_first(buffer_web, pattern_prevpage) if prev_page_url: prev_page = lutil.find_first(prev_page_url, pattern_pagenum) lutil.log('eso.main_list Value of prev_page: %s prev_page_url: "%s%s"' % (prev_page, root_url, prev_page_url)) prev_page_url = "%s%s" % (root_url, prev_page_url.replace('&', '&').replace('"', '"')) reset_cache = "yes" lutil.addDir(action="main_list", title="<< %s (%s)" % (translation(30106), prev_page), url=prev_page_url, reset_cache=reset_cache, genre=genre) # This is to force ".." option to go back to main index instead of previous page list. updateListing = reset_cache == "yes" for thumbnail, title, video_link in lutil.find_multiple(buffer_web, pattern_videos): video_info = {} url = '%s%s' % (root_url, video_link) if not 'http:' in thumbnail: thumbnail = '%s%s' % (root_url, thumbnail) title = title.strip().replace('"', '"').replace(''', '´').replace('&', '&') # Cleanup the title. video_info['Genre'] = genre video_info['Plot'] = title # Appends a new item to the xbmc item list lutil.addLink(action="play_video", title=title, url=url, thumbnail=thumbnail, video_info=video_info) # Here we get the next page URL to add it at the end of the current video list page. next_page_url = lutil.find_first(buffer_web, pattern_nextpage) if next_page_url: last_page = lutil.find_multiple(buffer_web, pattern_lastpage)[-1] next_page = lutil.find_first(next_page_url, pattern_pagenum) lutil.log('eso.main_list Value of next_page: %s last_page: %s next_page_url: "%s%s"' % (next_page, last_page, root_url, next_page_url)) next_page_url = "%s%s" % (root_url, next_page_url.replace('&', '&').replace('"', '"')) lutil.addDir(action="main_list", title=">> %s (%s/%s)" % (translation(30010), next_page, last_page), url=next_page_url, reset_cache=reset_cache, genre=genre) lutil.close_dir(pluginhandle, updateListing=updateListing)
def main_list(params): lutil.log("eso.main_list "+repr(params)) # Loads the web page from ESO with the video list. page_url = params.get("url") reset_cache = params.get("reset_cache") genre = params.get("genre") array_index = 0 if eso_url in page_url else 1 root_url = (eso_url, space_url)[array_index] buffer_web = lutil.carga_web(page_url) # Extract video items from the html content pattern_nextpage = '<a href="([^"]*?)">Next</a>' pattern_prevpage = '<a href="([^"]*?)">Previous</a>' pattern_lastpage = '<a href="[^"]*?">([0-9]+)</a>' pattern_pagenum = '/([0-9]+)/' pattern_videos = ('</span><img src="([^"]+)" class="[^"]+" alt="([^"]+)">.*?<a href="(/public/videos/[^"]*?)">', '</span><img src="([^"]+)" class="[^"]+" alt="([^"]+)">.*?<a href="(/videos/[^"]*?)">')[array_index] lutil.set_content_list(pluginhandle, 'tvshows') lutil.set_plugin_category(pluginhandle, genre) # We must setup the previous page entry from the second page onwards. prev_page_url = lutil.find_first(buffer_web, pattern_prevpage) if prev_page_url: prev_page = lutil.find_first(prev_page_url, pattern_pagenum) lutil.log('eso.main_list Value of prev_page: %s prev_page_url: "%s%s"' % (prev_page, root_url, prev_page_url)) prev_page_url = "%s%s" % (root_url, prev_page_url.replace('&', '&').replace('"', '"')) reset_cache = "yes" lutil.addDir(action="main_list", title="<< %s (%s)" % (translation(30106), prev_page), url=prev_page_url, reset_cache=reset_cache, genre=genre) # This is to force ".." option to go back to main index instead of previous page list. updateListing = reset_cache == "yes" for thumbnail, title, video_link in lutil.find_multiple(buffer_web, pattern_videos): video_info = {} url = '%s%s' % (root_url, video_link) if not thumbnail.startswith('http'): thumbnail = '%s%s' % (root_url, thumbnail) title = title.strip().replace('"', '"').replace(''', '´').replace('&', '&') # Cleanup the title. video_info['Genre'] = genre video_info['Plot'] = title # Appends a new item to the xbmc item list lutil.addLink(action="play_video", title=title, url=url, thumbnail=thumbnail, video_info=video_info) # Here we get the next page URL to add it at the end of the current video list page. next_page_url = lutil.find_first(buffer_web, pattern_nextpage) if next_page_url: last_page = lutil.find_multiple(buffer_web, pattern_lastpage)[-1] next_page = lutil.find_first(next_page_url, pattern_pagenum) lutil.log('eso.main_list Value of next_page: %s last_page: %s next_page_url: "%s%s"' % (next_page, last_page, root_url, next_page_url)) next_page_url = "%s%s" % (root_url, next_page_url.replace('&', '&').replace('"', '"')) lutil.addDir(action="main_list", title=">> %s (%s/%s)" % (translation(30010), next_page, last_page), url=next_page_url, reset_cache=reset_cache, genre=genre) lutil.close_dir(pluginhandle, updateListing=updateListing)
def get_playable_url(url): """This function returns a playable URL parsing the different video sources available from the iframe link""" video_patterns = ( ('vimeo1', 'vimeo.com/video/([0-9]+)', 'vimeo'), ('vimeo2', 'vimeo.com%2Fvideo%2F([0-9]+)', 'vimeo'), ('youtube1', 'videoId: "([0-9A-Za-z_-]{11})', 'youtube'), ('youtube2', 'youtube.com%2Fwatch%3Fv%3D([0-9A-Za-z_-]{11})', 'youtube'), ('youtube3', 'youtube.com%2Fembed%2F([0-9A-Za-z_-]{11})', 'youtube'), ('youtube4', 'youtube.com/embed/([0-9A-Za-z_-]{11})', 'youtube'), ('dailymotion1', ' src="[htp:]*?//www.dailymotion.com/embed/video/([0-9a-zA-Z]+)', 'dailymotion'), ('dailymotion2', 'www.dailymotion.com%2Fembed%2Fvideo%2F(.*?)%', 'dailymotion'), ('archiveorg1', ' src="(https://archive.org/embed/[^"]*?)"', 'archiveorg'), ('kickstarter1', ' src="(https://www.kickstarter.com/[^"]*?)"', 'kickstarter'), ('tagtele1', ' src="(http://www.tagtele.com/embed/[^"]*?)"', 'tagtele'), ) buffer_url = l.carga_web(url) for pattern_name, pattern, source in video_patterns: video_id = l.find_first(buffer_url, pattern) if video_id: l.log('We have found this video_id "%s" using the pattern: "%s"' % (video_id, pattern_name)) try: playable_url = eval("get_playable_%s_url(video_id)" % source) break except: l.log("There was a problem using the pattern '%s' on this video link: '%s'\n" % (pattern_name, url)) return '' else: l.log("Sorry, but we cannot support the type of video for this link yet:\n'%s'" % url) playable_url = '' return playable_url
def get_create_index(): """This function gets the the first level index menu.""" menu_entries = ( ( 'menu_grille', '<label class="all selected">.*?<span>(.*?)</span></label>', 'all'), ( 'menu_grille', '<label class="news">.*?<span>(.*?)</span></label>', 'reportage'), ( 'menu_sec', '<a href="/emissions/">(.*?)</a>', 'emissions'), ( 'menu_sec', '<a href="/chroniques/">(.*?)</a>', 'chroniques'), ( 'menu_sec', '<a href="/series/">(.*?)</a>', 'series'), ( 'video_docs', '<h1 class="tt">(Les Docs)</h1>', ''), ( 'search_videos', '<a href="#recherche">(.*?)</a>', ''), ) buffer_url = l.carga_web(root_url) level_options = get_two_level_menu(buffer_url) menu_list = [] for action, menu_pattern, menu_opt in menu_entries: title = l.find_first(buffer_url, menu_pattern) if title: menu_entry = { 'action' : action, 'title' : title, } if action == 'menu_grille': menu_entry['themes'] = level_options['catalogue'] menu_entry['sorting'] = level_options['order'] menu_entry['ctype'] = menu_opt if action == 'menu_sec': menu_entry['menus'] = level_options[menu_opt] menu_list.append(menu_entry) l.log('contents of menu_list:\n%s' % repr(menu_list)) return menu_list
def get_playable_url(url): """This function returns a playable URL parsing the different video sources available from the iframe link""" video_patterns = ( ('dailymotion1', '"[htp:]*?//www.dailymotion.com[/]+?video/([^"]*?)"', 'dailymotion'), ('dailymotion2', '"[htp:]*?//www.dailymotion.com/embed/video/([^"]*?)"', 'dailymotion'), ('dailymotion3', 'www.dailymotion.com%2Fembed%2Fvideo%2F(.*?)%', 'dailymotion'), ('youtube1', 'videoId: "([0-9A-Za-z_-]{11})', 'youtube'), ('youtube2', 'youtube.com/watch\?v=([0-9A-Za-z_-]{11})', 'youtube'), ('youtube3', 'youtube.com%2Fembed%2F([0-9A-Za-z_-]{11})', 'youtube'), ('youtube4', 'youtube.com/embed/([0-9A-Za-z_-]{11})', 'youtube'), ('vimeo1', 'vimeo.com/video/([0-9]+)', 'vimeo'), ('vimeo2', 'vimeo.com%2Fvideo%2F([0-9]+)', 'vimeo'), ('vimeo3', 'vimeo.com/([0-9]+)', 'vimeo'), ('vimeo4', 'vimeo.com/moogaloop.swf\?clip_id=([0-9]+)', 'vimeo'), ) buffer_url = l.carga_web(url) for pattern_name, pattern, source in video_patterns: video_id = l.find_first(buffer_url, pattern) if video_id: l.log('We have found this video_id "%s" using the pattern: "%s"' % (video_id, pattern_name)) playable_url = eval("get_playable_%s_url(video_id)" % source) break else: l.log("Sorry, but we cannot support the type of video for this link yet:\n'%s'" % url) playable_url = '' return playable_url
def get_playable_url(url): """This function returns a playable URL parsing the different video sources available from the iframe link""" video_patterns = ( ('dailymotion1', 'www.dailymotion.com[/]+?video/([0-9a-zA-Z]+)', 'dailymotion'), ('dailymotion2', 'www.dailymotion.com/embed/video/([0-9a-zA-Z]+)', 'dailymotion'), ('dailymotion3', 'www.dailymotion.com%2Fembed%2Fvideo%2F([0-9a-zA-Z]+)', 'dailymotion'), ('youtube1', 'videoId: "([0-9A-Za-z_-]{11})', 'youtube'), ('youtube2', 'youtube.com/watch\?v=([0-9A-Za-z_-]{11})', 'youtube'), ('youtube3', 'youtube.com%2Fembed%2F([0-9A-Za-z_-]{11})', 'youtube'), ('youtube4', 'youtube.com/embed/([0-9A-Za-z_-]{11})', 'youtube'), ('vimeo1', 'vimeo.com/video/([0-9]+)', 'vimeo'), ('vimeo2', 'vimeo.com%2Fvideo%2F([0-9]+)', 'vimeo'), ('vimeo3', 'vimeo.com/([0-9]+)', 'vimeo'), ('vimeo4', 'vimeo.com/moogaloop.swf\?clip_id=([0-9]+)', 'vimeo'), ) buffer_url = l.carga_web(url) for pattern_name, pattern, source in video_patterns: video_id = l.find_first(buffer_url, pattern) if video_id: l.log('We have found this video_id "%s" using the pattern: "%s"' % (video_id, pattern_name)) playable_url = eval("get_playable_%s_url(video_id)" % source) break else: l.log("Sorry, but we cannot support the type of video for this link yet:\n'%s'" % url) playable_url = '' return playable_url
def parse_menu_hackaround(source_url, html_buffer): """This function is a'hackaround to parse and extract the video list info from the 'Un Bien Belge Histoire' program, due to its special contents. """ title_pattern = '<meta property="og:title" content="(.*?)"' plot_pattern = '<meta property="og:description" content="(.*?)"' thumb_pattern = '<meta property="og:image" content="(.*?)"' video_block_pattern = '<h2>Sur le même sujet</h2>[^<]*?<ul>(.*?)</ul>' url_item_pattern = '<a href="(.*?)"' thumb_item_pattern = '<img src="(.*?)"' title_item_pattern = '<span>(.*?)</span>' thumbnail_url = l.find_first(html_buffer, thumb_pattern) video_list = [ { 'url' : source_url, 'title' : l.get_clean_title(l.find_first(html_buffer, title_pattern)), 'plot' : l.get_clean_title(l.find_first(html_buffer, plot_pattern)), 'thumbnail' : sanitize_url(thumbnail_url), 'IsPlayable' : True, }, ] video_block = l.find_first(html_buffer, video_block_pattern) for video_item in video_block.split('</a>'): thumbnail_url = l.find_first(video_item, thumb_item_pattern) item = { 'url' : l.find_first(video_item, url_item_pattern), 'title' : l.get_clean_title(l.find_first(video_item, title_item_pattern)), 'thumbnail' : sanitize_url(thumbnail_url), 'IsPlayable' : True, } video_list.append(item) return video_list
def parse_menu_hackaround(source_url, html_buffer): """This function is a'hackaround to parse and extract the video list info from the 'Un Bien Belge Histoire' program, due to its special contents. """ title_pattern = '<meta property="og:title" content="(.*?)"' plot_pattern = '<meta property="og:description" content="(.*?)"' thumb_pattern = '<meta property="og:image" content="(.*?)"' video_block_pattern = '<h2>Sur le même sujet</h2>[^<]*?<ul>(.*?)</ul>' url_item_pattern = '<a href="(.*?)"' thumb_item_pattern = '<img src="(.*?)"' title_item_pattern = '<span>(.*?)</span>' thumbnail_url = l.find_first(html_buffer, thumb_pattern) video_list = [ { 'url' : source_url, 'title' : get_clean_title(l.find_first(html_buffer, title_pattern)), 'plot' : get_clean_title(l.find_first(html_buffer, plot_pattern)), 'thumbnail' : l.sanitize_url(thumbnail_url), 'IsPlayable' : True, }, ] video_block = l.find_first(html_buffer, video_block_pattern) for video_item in video_block.split('</a>'): thumbnail_url = l.find_first(video_item, thumb_item_pattern) item = { 'url' : l.find_first(video_item, url_item_pattern), 'title' : get_clean_title(l.find_first(video_item, title_item_pattern)), 'thumbnail' : l.sanitize_url(thumbnail_url), 'IsPlayable' : True, } video_list.append(item) return video_list
def get_playable_vimeo_url(video_id): """This function returns the playable URL for the Vimeo embedded video from the video_id retrieved. This is a workaround to avoid the problem found with the Vimeo Add-on running on Gotham. On Frodo, calling the Vimeo Add-on with the video_id works great.""" video_pattern_sd = '"sd":{.*?,"url":"([^"]*?)"' video_info_url = 'https://player.vimeo.com/video/' + video_id buffer_link = l.carga_web(video_info_url) return l.find_first(buffer_link, video_pattern_sd)
def get_video_docs(): """This function gets the Documentals video list from the main page website.""" section_sep = '<div id="docs">' entry_pattern = '<article class="illustrated">(.*?)</article>' video_entry_title = '<h2><a href="[^>]*?>(.*?)</a></h2>' video_entry_themes = ' rel="tag">(.*?)</a>' video_entry_views = '<li class="views"><span>(.*?)<span class="for-reader">(.*?)</span></span></li>' video_entry_rating = 'ratings_off\(([^,]*?)' video_entry_url = '<a href="([^"]*?)"><img width="[^"]*?" height="[^"]*?" src="([^"]*?)"' video_entry_plot = '<div class="chapeau">.*?<p>(.*?)</p>' video_entry_date = '<span class="date"><time datetime="([^T]*?)T[^"]*?">(.*?)</time>' video_entry_author = '<span class="author">(.*?)<a href="[^>]*?>(.*?)</a>' root_url = 'http://latelelibre.fr/' buffer_url = l.carga_web(root_url) video_list = [] docs_contents = buffer_url.split(section_sep)[1] or '' for video_entry in l.find_multiple(docs_contents, entry_pattern): title = l.find_first(video_entry, video_entry_title) url, thumb = l.find_first(video_entry, video_entry_url) or ('', '') views = "%s%s" % l.find_first(video_entry, video_entry_views) or ('', '') rating = l.find_first(video_entry, video_entry_rating) plot = l.find_first(video_entry, video_entry_plot) timestamp, date = l.find_first(video_entry, video_entry_date) or ('', '') author_label, author = l.find_first(video_entry, video_entry_author) or ('', '') theme_list = '' for itheme in l.find_multiple(video_entry, video_entry_themes): theme_list = '%s %s' % (theme_list, itheme) year, month, day = timestamp.split('-') or ('', '', '') l.log('Video info. title: "%s"\nviews: "%s" timestamp: "%s" date: "%s" author: "%s"' % (title, views, timestamp, date, author)) video_entry = { 'url' : url, 'title' : "%s (%s/%s/%s)" % ( get_clean_title(title), day, month, year, ), 'thumbnail' : l.sanitize_url(thumb), 'plot' : "%s\n%s\n%s %s %s %s %s" % ( get_clean_title(plot), date, theme_list, views, rating, get_clean_title(author_label), author ), 'rating' : rating, 'genre' : theme_list.strip(), 'year' : year, 'credits' : author, 'IsPlayable' : True } video_list.append(video_entry) return video_list
def parse_video_list(html): """This function parses the video list from the HTML content retrieved from the website""" item_sep = 'data-id' video_entry_pattern ='^="([0-9]+?)" data-title="([^"]*?)" data-type="[^"]*?" data-theme="([^"]*?)" data-timestamp="[^"]*?" data-views="([^"]*?)" data-comments="[^"]*?" data-rating="([^"]*?)">' video_entry_url = '<div class="illustration">[^<]*?<a href="([^"]*?)"><img width="[^"]*?" height="[^"]*?" src="([^"]*?)"' video_entry_plot = '<div class="chapeau">.*?<p>(.*?)</p>' video_entry_date = '<p class="date"><span class="for-reader">(.*?)</span><time datetime="([^T]*?)T[^"]*?">(.*?)</time>' video_entry_author = ' rel="author">(.*?)</a>' video_author_label = '<p class="author">(.*?)<' video_views_label = '<li class="views"><span>.*?<span class="for-reader">(.*?)</span></span></li>' video_ids = [] video_list = [] author_label = l.get_clean_title(l.find_first(html, video_author_label)) or '=>' views_label = l.find_first(html, video_views_label) or '(0)' for video_section in html.split(item_sep): video_id, title, theme, views, rating = l.find_first(video_section, video_entry_pattern) or ('', '', '', '0', '0') if video_id: video_ids.append(video_id) url, thumb = l.find_first(video_section, video_entry_url) or ('', '') l.log('Video info: video_id: "%s" url: "%s" thumb: "%s" title: "%s" category: "%s" views: "%s" rating: "%s"' % (video_id, url, thumb, title, theme, views, rating)) plot = l.find_first(video_section, video_entry_plot) date_text, timestamp, date = l.find_first(video_section, video_entry_date) or ('', '', '') year, month, day = timestamp.split('-') or ('', '', '') author = l.find_first(video_section, video_entry_author) l.log('Video info: plot: "%s"' % plot) l.log('Video info: date_text: "%s" timestamp: "%s" date: "%s" author: "%s"' % (date_text, timestamp, date, author)) l.log('==================================================================================================================================================================') video_entry = { 'url' : url, 'title' : "%s (%s/%s/%s)" % ( l.get_clean_title(title), day, month, year, ), 'thumbnail' : sanitize_url(thumb), 'plot' : "%s\n%s%s\n%s %s%s %s* %s %s" % ( l.get_clean_title(plot), date_text, date, theme, views, views_label, rating, author_label, author, ), 'rating' : rating, 'genre' : theme, 'year' : year, 'credits' : author, 'IsPlayable' : True } video_list.append(video_entry) return video_list, video_ids
def get_playable_url(url): """This function gets the stream url for direct channels.""" playable_url_pattern = '))3pm|oidua.tsaceci:?(?*.ptth('[::-1] buffer_url = l.carga_web(url) stream_url = l.find_first(buffer_url, playable_url_pattern) l.log('get_playable_url has found this URL for direct playback. url: "%s"' % stream_url) return stream_url
def get_video_docs(): """This function gets the Documentals video list from the main page website.""" section_sep = '<div id="docs">' entry_pattern = '<article class="illustrated">(.*?)</article>' video_entry_title = '<h2><a href="[^>]*?>(.*?)</a></h2>' video_entry_themes = ' rel="tag">(.*?)</a>' video_entry_views = '<li class="views"><span>(.*?)<span class="for-reader">(.*?)</span></span></li>' video_entry_rating = 'ratings_off\(([^,]*?)' video_entry_url = '<a href="([^"]*?)"><img width="[^"]*?" height="[^"]*?" src="([^"]*?)"' video_entry_plot = '<div class="chapeau">.*?<p>(.*?)</p>' video_entry_date = '<span class="date"><time datetime="([^T]*?)T[^"]*?">(.*?)</time>' video_entry_author = '<span class="author">(.*?)<a href="[^>]*?>(.*?)</a>' buffer_url = l.carga_web(root_url) video_list = [] docs_contents = buffer_url.split(section_sep)[1] or '' for video_entry in l.find_multiple(docs_contents, entry_pattern): title = l.find_first(video_entry, video_entry_title) url, thumb = l.find_first(video_entry, video_entry_url) or ('', '') views = "%s%s" % l.find_first(video_entry, video_entry_views) or ('', '') rating = l.find_first(video_entry, video_entry_rating) plot = l.find_first(video_entry, video_entry_plot) timestamp, date = l.find_first(video_entry, video_entry_date) or ('', '') author_label, author = l.find_first(video_entry, video_entry_author) or ('', '') theme_list = '' for itheme in l.find_multiple(video_entry, video_entry_themes): theme_list = '%s %s' % (theme_list, itheme) year, month, day = timestamp.split('-') or ('', '', '') l.log('Video info. title: "%s"\nviews: "%s" timestamp: "%s" date: "%s" author: "%s"' % (title, views, timestamp, date, author)) video_entry = { 'url' : url, 'title' : "%s (%s/%s/%s)" % ( l.get_clean_title(title), day, month, year, ), 'thumbnail' : sanitize_url(thumb), 'plot' : "%s\n%s\n%s %s %s %s %s" % ( l.get_clean_title(plot), date, theme_list, views, rating, l.get_clean_title(author_label), author ), 'rating' : rating, 'genre' : theme_list.strip(), 'year' : year, 'credits' : author, 'IsPlayable' : True } video_list.append(video_entry) return video_list
def parse_video_list(html): """This function parses the video list from the HTML content retrieved from the website""" item_sep = 'data-id' video_entry_pattern ='^="([0-9]+?)" data-title="([^"]*?)" data-type="[^"]*?" data-theme="([^"]*?)" data-timestamp="[^"]*?" data-views="([^"]*?)" data-comments="[^"]*?" data-rating="([^"]*?)">' video_entry_url = '<div class="illustration">[^<]*?<a href="([^"]*?)"><img width="[^"]*?" height="[^"]*?" src="([^"]*?)"' video_entry_plot = '<div class="chapeau">.*?<p>(.*?)</p>' video_entry_date = '<p class="date"><span class="for-reader">(.*?)</span><time datetime="([^T]*?)T[^"]*?">(.*?)</time>' video_entry_author = ' rel="author">(.*?)</a>' video_author_label = '<p class="author">(.*?)<' video_views_label = '<li class="views"><span>.*?<span class="for-reader">(.*?)</span></span></li>' video_ids = [] video_list = [] author_label = get_clean_title(l.find_first(html, video_author_label)) or '=>' views_label = l.find_first(html, video_views_label) or '(0)' for video_section in html.split(item_sep): video_id, title, theme, views, rating = l.find_first(video_section, video_entry_pattern) or ('', '', '', '0', '0') if video_id: video_ids.append(video_id) url, thumb = l.find_first(video_section, video_entry_url) or ('', '') l.log('Video info. video_id: "%s" url: "%s" thumb: "%s" title: "%s" category: "%s" views: "%s" rating: "%s"' % (video_id, url, thumb, title, theme, views, rating)) plot = l.find_first(video_section, video_entry_plot) date_text, timestamp, date = l.find_first(video_section, video_entry_date) or ('', '', '') year, month, day = timestamp.split('-') or ('', '', '') author = l.find_first(video_section, video_entry_author) l.log('Video info. plot: "%s"\ndate_text: "%s" timestamp: "%s" date: "%s" author: "%s"' % (plot, date_text, timestamp, date, author)) video_entry = { 'url' : url, 'title' : "%s (%s/%s/%s)" % ( get_clean_title(title), day, month, year, ), 'thumbnail' : l.sanitize_url(thumb), 'plot' : "%s\n%s%s\n%s %s%s %s* %s %s" % ( get_clean_title(plot), date_text, date, theme, views, views_label, rating, author_label, author, ), 'rating' : rating, 'genre' : theme, 'year' : year, 'credits' : author, 'IsPlayable' : True } video_list.append(video_entry) return video_list, video_ids
def get_playable_dailymotion_url(video_id): """This function returns the playable URL for the Dalymotion embedded video from the video_id retrieved.""" daily_video_pattern = '"%s":\[[^]]*{"type":"video\\\/mp4","url":"(.+?)"' daily_video_qualities = ('1080', '720', '480', '380', '240', '144') daily_url = 'http://www.dailymotion.com/embed/video/' + video_id buffer_link = l.carga_web(daily_url) for video_quality in daily_video_qualities: video_url = l.find_first(buffer_link, daily_video_pattern % video_quality) if video_url: return video_url.replace('\\','') return ''
def get_playable_url(url): """This function gets the stream url for direct channels.""" playable_url_pattern = '(http[^#]+)' buffer_url = l.carga_web(url) stream_url = l.find_first(buffer_url, playable_url_pattern) l.log( 'get_playable_url has found this URL for direct playback. url: "%s"' % stream_url) return stream_url
def play_video(params): lutil.log("tv5monde.play_video "+repr(params)) buffer_link = lutil.carga_web(params.get("url")) pattern_player = '<videoUrl>([^<]+)</videoUrl>.*?<appleStreamingUrl>([^<]*)</appleStreamingUrl>' smil_url, video_url = lutil.find_first(buffer_link, pattern_player) if video_url: lutil.log('tv5monde.play_video: We have found the URL of the video file: "%s" and going to play it!!' % video_url) return lutil.play_resolved_url(pluginhandle = pluginhandle, url = video_url) else: lutil.log('tv5monde.play: We did not find the video file URL because it is very old. We have to load the smil URL and get the info from there: "%s"' % smil_url) buffer_smil = lutil.carga_web(smil_url) pattern_smil = '<video src="(tv5mondeplus/hq/[^"]+)"' video_source = lutil.find_first(buffer_smil, pattern_smil) if video_source: video_smil = 'http://dlhd.tv5monde.com/%s' % video_source lutil.log('tv5monde.play_video: We have found the URL of the video file: "%s" and going to play it!!' % video_smil) return lutil.play_resolved_url(pluginhandle = pluginhandle, url = video_smil) else: lutil.log("tv5monde.play_video: We did not find the video file URL from the smil info. We cannot play it!!") lutil.showWarning(translation(30011))
def get_playable_search_url(url): """This function gets the media url from the search url link.""" playable_url_pattern = '<link rel="audio_src" href="([^"]*?)"' url_options = ')ung-xunil(02%4.91.1F2%tegW=tnegA-resU|'[::-1] buffer_url = l.carga_web(url) media_url = l.find_first(buffer_url, playable_url_pattern) l.log( 'get_playable_search_url has found this URL for playback. url: "%s"' % media_url) return media_url + url_options
def play_video(params): lutil.log("esa.play "+repr(params)) buffer_link = lutil.carga_web(params.get("url")) if language != 'en': pattern_lang = '<li><a href="([^\(]*?\(lang\)/%s)" >' % language video_link = lutil.find_first(buffer_link, pattern_lang) if video_link: lang_url = '%s%s' % (root_url, video_link) lutil.log("esa.play: We have found this alt video URL for '%s' language: '%s'" % (language, lang_url)) buffer_link = lutil.carga_web(lang_url) pattern_video = '<a href="([^"]*?)" id="download_link"' video_url = lutil.find_first(buffer_link, pattern_video) if video_url: try: lutil.log("esa.play: We have found this video: '%s' and let's going to play it!" % video_url) return lutil.play_resolved_url(pluginhandle = pluginhandle, url = video_url) except: lutil.log('esa.play ERROR: we cannot reproduce this video URL: "%s"' % video_url) return lutil.showWarning(translation(30012)) lutil.log('esa.play ERROR: we cannot play the video from this source yet: "%s"' % params.get("url")) return lutil.showWarning(translation(30011))
def index(params): lutil.log("tv5monde.index "+repr(params)) url = 'http://www.tv5mondeplus.com/videos' buffer_html = lutil.carga_web(url) list_pattern = '<div id="tri-par-genre"(.+?)</ul>' lista_genre = lutil.find_first(buffer_html, list_pattern) genre_pattern = '<li><a id="([0-9]+)" [^>]+>([^<]+)<' for genre, label in lutil.find_multiple(lista_genre, genre_pattern): genre_url = 'http://www.tv5mondeplus.com/get/videos?pg=0&type=genre&sort=%s&loadpg=false&order=date' % genre lutil.log('tv5monde.index url=["%s"] genre=["%s"]' % (genre_url, label)) lutil.addDir(action="main_list", title=label, url=genre_url) lutil.close_dir(pluginhandle)
def get_video_sec(url): """This function gets the video list for Emissions, Chroniques, Series, and Search sections.""" pattern_next = '<li class="next"><a href="([^"]*?)">(.*?)</a></li>' buffer_url = l.carga_web(url) video_list, video_ids = parse_video_list(buffer_url) if not len(video_list): # This is a "kackaround" for "Un Bien Belge Histoire" special menu. video_list = parse_menu_hackaround(url, buffer_url) # This section is for the Search menu Next Page entry. next_url, next_label = l.find_first(buffer_url, pattern_next) or ('', '') if next_url: item_next = { 'url' : next_url, 'title' : ">> %s" % next_label, 'IsPlayable' : False, } video_list.append(item_next) return video_list
def get_create_index(): """This function gets the the first level index menu.""" main_url = root_url + 'sanedac#/enr/atracala/'[::-1] menu_patterns = (('menu_direct', 'href="([^"]*?)".*?([Rr]adio [Ee]n [Dd]irecto)'), ) buffer_url = l.carga_web(main_url) menu_entries = get_channels_menu(buffer_url) for action, pattern in menu_patterns: url, title = l.find_first(buffer_url, pattern) or ('', '') menu_item = { 'action': action, 'title': get_clean_title(title), 'args': root_url + url, } menu_entries.append(menu_item) return menu_entries
def get_create_index(): """This function gets the the first level index menu.""" root_url = 'http://latelelibre.fr' menu_entries = ( ( 'menu_grille', '<label class="all selected">.*?<span>(.*?)</span></label>', 'all'), ( 'menu_grille', '<label class="news">.*?<span>(.*?)</span></label>', 'reportage'), ( 'menu_sec', '<a href="/emissions/">(.*?)</a>', 'emissions'), ( 'menu_sec', '<a href="/chroniques/">(.*?)</a>', 'chroniques'), ( 'menu_sec', '<a href="/series/">(.*?)</a>', 'series'), ( 'video_docs', '<h1 class="tt">(Les Docs)</h1>', ''), ( 'search_videos', '<a href="#recherche">(.*?)</a>', ''), ) buffer_url = l.carga_web(root_url) level_options = get_two_level_menu(buffer_url) menu_list = [] for action, menu_pattern, menu_opt in menu_entries: title = l.find_first(buffer_url, menu_pattern) if title: menu_entry = { 'action' : action, 'title' : title, } if action == 'menu_grille': menu_entry['themes'] = level_options['catalogue'] menu_entry['sorting'] = level_options['order'] menu_entry['ctype'] = menu_opt if action == 'menu_sec': menu_entry['menus'] = level_options[menu_opt] menu_list.append(menu_entry) l.log('valor de menu_list:\n%s' % repr(menu_list)) return menu_list
def get_create_index(): """This function gets the the first level index menu.""" main_url = root_url + '/tsacdop/oidar/'[::-1] menu_patterns = ( ( 'program_list', '<a href="([^"]*?)" title="(Listado de programas)"><span>'), ( 'menu_direct', 'href="([^"]*?)".*?([Ee]n [Dd]irecto)'), ) buffer_url = l.carga_web(main_url) menu_entries = get_two_level_menu(buffer_url) for action, pattern in menu_patterns: url, title = l.find_first(buffer_url, pattern) or ('', '') if url: menu_item = { 'action' : action, 'title' : get_clean_title(title).capitalize(), 'args' : url, } menu_entries.append(menu_item) return menu_entries
def main_list(params): lutil.log("esa.main_list " + repr(params)) # Loads the web page from ESA with the video list. page_url = params.get("url") reset_cache = params.get("reset_cache") genre = params.get("genre") buffer_web = lutil.carga_web(page_url) # Extract video items from the html content pattern_currentpage = '<span class="current">([^<]*?)</span>' pattern_page_url = '^%s([^\?]+)' pattern_nextpage = '<span class="next"><a href="([^"]*?)">' pattern_prevpage = '<span class="previous"><a href="([^"]*?)">' pattern_last = '<span class="other"><a href="[^"]*?">([^<]+)</a></span>' pattern_videos = '<div class="psr_item_grid">(.*?)</div>' pattern_videolink = '<a href="([^"]*?)"' pattern_thumbnail = '<img src="([^"]*?)"' pattern_title = '<span class="line2hell">([^<]+)</span>' pattern_date = '<span class="date">([^<]*?)</span>' pattern_year = '([0-9]{4})' lutil.set_content_list(pluginhandle, 'tvshows') lutil.set_plugin_category(pluginhandle, genre) page_current = lutil.find_first(buffer_web, pattern_currentpage) or '1' page_url_pref = lutil.find_first(page_url, pattern_page_url % root_url) # We must setup the previous page entry from the second page onwards. if page_current != '1': prev_page_url = lutil.find_first(buffer_web, pattern_prevpage) lutil.log('esa.main_list Value of current_page_url: "%s"' % page_url) prev_page_pref = lutil.find_first(prev_page_url, pattern_page_url % '') prev_page_url = page_url.replace(page_url_pref, prev_page_pref) reset_cache = "yes" lutil.addDir(action="main_list", title="<< %s (%s)" % (translation(30106), (int(page_current) - 1)), url=prev_page_url, reset_cache=reset_cache, genre=genre) # This is to force ".." option to go back to main index instead of previous page list. updateListing = reset_cache == "yes" videolist = lutil.find_multiple(buffer_web, pattern_videos) for video_entry in videolist: video_info = {} video_link = lutil.find_first(video_entry, pattern_videolink) thumbnail_link = lutil.find_first(video_entry, pattern_thumbnail) title = lutil.find_first(video_entry, pattern_title) title = title.replace('"', '"').replace(''', '´').replace( '&', '&') # Cleanup the title. date = lutil.find_first(video_entry, pattern_date).strip().replace(' ', '') if date: video_info['Year'] = lutil.find_first(date, pattern_year) title = '%s (%s)' % (title, date) url = '%s%s' % (root_url, video_link) thumbnail = '%s%s' % (root_url, thumbnail_link) video_info['Genre'] = genre video_info[ 'Plot'] = title # The description only appears when we load the link. lutil.log( 'esa.main_list Videolist: URL: "%s" Title: "%s" Thumbnail: "%s"' % (url, title, thumbnail)) # Appends a new item to the xbmc item list lutil.addLink(action="play_video", title=title, url=url, thumbnail=thumbnail, video_info=video_info, show_fanart=show_fanart) # Here we get the next page URL to add it at the end of the current video list page. next_page_url = lutil.find_first(buffer_web, pattern_nextpage) if next_page_url: next_page_pref = lutil.find_first(next_page_url, pattern_page_url % '') last_page = lutil.find_multiple(buffer_web, pattern_last)[-1] or '' lutil.log("esa.main_list Value of last_page: %s" % last_page) lutil.log('esa.main_list Value of current_page_url: "%s"' % page_url) next_page_url = page_url.replace(page_url_pref, next_page_pref) lutil.addDir(action="main_list", title=">> %s (%s/%s)" % (translation(30010), int(page_current) + 1, last_page), url=next_page_url, reset_cache=reset_cache, genre=genre) lutil.close_dir(pluginhandle, updateListing=updateListing)
def get_search_list(search_url, localized=lambda x: x): """This function gets the list of items returned by the search engine.""" search_section_sep = '<div class="txtBox">' search_link_pattern = '<a href="([^"]*?)"' search_title_pattern = '<span class="maintitle">(.*?)</span>' search_desc_pattern = '<div class="auxBox">[^<]*?<p>(.*?)</p>' search_year_pattern = '<span class="datpub">[0-9]+.[0-9]+.([0-9]+)</span>' page_num_pattern = 'start=([0-9]+)' # Starts by 1. page_url_pattern = 'start=%d&' buffer_url = l.carga_web(search_url) search_list = [] reset_cache = False current_page_num = int(l.find_first(search_url, page_num_pattern) or '1') if current_page_num != 1: prev_page_num = current_page_num - 1 previous_page_url = search_url.replace( page_url_pattern % current_page_num, page_url_pattern % prev_page_num) search_entry = { 'url': previous_page_url, 'title': '<< %s (%d)' % (localized('Previous page'), prev_page_num), 'action': 'search_list', 'IsPlayable': False } search_list.append(search_entry) reset_cache = True for search_section in buffer_url.split(search_section_sep)[1:]: year = l.find_first(search_section, search_year_pattern) title = l.find_first(search_section, search_title_pattern).strip() desc = l.find_first(search_section, search_desc_pattern).strip() url = l.find_first(search_section, search_link_pattern) l.log('Podcast info. url: "%s" title: "%s"' % (url, get_clean_title(title))) search_entry = { 'url': url, 'title': get_clean_title(title), 'comment': get_clean_title(desc.replace('&', '&')), 'year': year, 'action': 'play_search', 'IsPlayable': True, } search_list.append(search_entry) next_page_num = current_page_num + 1 if l.find_first(buffer_url, page_url_pattern % next_page_num): next_page_url = search_url.replace(page_url_pattern % current_page_num, page_url_pattern % next_page_num) search_entry = { 'url': next_page_url, 'title': '>> %s (%d)' % (localized('Next page'), next_page_num), 'action': 'search_list', 'IsPlayable': False } search_list.append(search_entry) return {'search_list': search_list, 'reset_cache': reset_cache}
def get_audio_list(program_url, localized=lambda x: x): """This function makes the emissions list data structure for all the programmes.""" audio_section_sep = '<span class="col_tit" ' audio_fecha_pattern = '<span class="col_fec">([^<]*?)</span>' audio_dur_pattern = '<span class="col_dur">([^<]*?)</span>' audio_title_pattern = '<span class="titulo-tooltip"><a href="[^"]*?" title="[^>]*?>([^<]*?)</a></span>' audio_desc_pattern = '<span class="detalle">(.*?)</span>' audio_link_pattern = '<span class="col_tip">.*?<a href="(http.*?mp[34])"' audio_rating_pattern = '<span class="col_pop"><span title="([^"]*?)" class="pc([0-9]*?)">' audio_year_pattern = '([0-9]{4})' page_num_pattern = 'pbq=([0-9]+)' page_url_pattern = '<a name="paginaIR" href="([^"]*?)"><span>%s' page_num_url_pattern = '<a name="paginaIR" href=".*?pbq=([0-9]+)[^"]*?"><span>%s' buffer_url = l.carga_web(program_url) audio_list = [] reset_cache = False this_year = l.get_this_year() curr_page_num = l.find_first(program_url, page_num_pattern) or '1' if curr_page_num != '1': previous_page_url = l.find_first(buffer_url, page_url_pattern % 'Anterior') prev_page_num = l.find_first(previous_page_url, page_num_pattern) audio_entry = { 'url' : root_url + previous_page_url.replace('&', '&'), 'title' : '<< %s (%s)' % (localized('Previous page'), prev_page_num), 'action' : 'audio_list', 'IsPlayable' : False } audio_list.append(audio_entry) reset_cache = True for audio_section in buffer_url.split(audio_section_sep)[1:]: date = l.find_first(audio_section, audio_fecha_pattern) duration = l.find_first(audio_section, audio_dur_pattern) or '00:00:00' title = l.find_first(audio_section, audio_title_pattern) desc = l.find_first(audio_section, audio_desc_pattern) url = l.find_first(audio_section, audio_link_pattern) rtlabel, rating = l.find_first(audio_section, audio_rating_pattern) or ('', '1') year = int(l.find_first(date, audio_year_pattern) or '0') or this_year tduration = duration.split(':') if len(tduration) == 3: seconds = str(int(tduration[-3] or '0') * 3600 + int(tduration[-2] or '0') * 60 + int(tduration[-1] or '0')) elif len(tduration) == 2: seconds = str(int(tduration[-2] or '0') * 60 + int(tduration[-1] or '0')) else: seconds = tduration[-1] l.log('Podcast info. url: "%s" duration: "%s" seconds: "%s" title: "%s" rating: "%s" date: "%s"' % ( url, duration, seconds, title, rating, date)) audio_entry = { 'url' : url, 'title' : "%s (%s)" % ( get_clean_title(title), date, ), 'comment' : "%s\n%s - %s - %s" % ( get_clean_title(desc), duration, date, rtlabel, ), 'rating' : int(rating)//20, # Rating goes from 0 to 5 in audio media. 'duration' : seconds, 'year' : year, 'action' : 'play_audio', 'IsPlayable' : True, } if url: # This is to make sure the URL is valid. audio_list.append(audio_entry) last_page_num = l.find_first(buffer_url, page_num_url_pattern % 'Último') if last_page_num and curr_page_num != last_page_num: next_page_url = l.find_first(buffer_url, page_url_pattern % 'Siguiente') next_page_num = l.find_first(next_page_url, page_num_pattern) audio_entry = { 'url' : root_url + next_page_url.replace('&', '&'), 'title' : '>> %s (%s/%s)' % (localized('Next page'), next_page_num, last_page_num), 'action' : 'audio_list', 'IsPlayable' : False } audio_list.append(audio_entry) return { 'audio_list': audio_list, 'reset_cache': reset_cache }
def get_program_list(menu_url, all_programmes_flag=False, localized=lambda x: x): """This function makes programmes list data structure for all the program sections.""" program_section_sep = '<span class="col_tit"' program_fecha_pattern = '<span class="col_fec">([^<]*?)</span>' program_canal_pattern = "title=\"Ir a portada de '([^']*?)'" program_desc_pattern = '<span class="detalle">(.*?)</span>' program_link_pattern = '<span class="titulo-tooltip"><a href="([^"]*?)" title="[^>]*?>([^<]*?)</a></span>' program_genre_pattern = '<span class="col_cat">([^<]*?)</span>' page_num_pattern = '/([0-9]+)/' page_url_pattern = '<a name="paginaIR" href="([^"]*?)"><span>%s' page_num_url_pattern = '<a name="paginaIR" href=".*?/([0-9]+)/[^"]*?"><span>%s' # This toggles between only on emission and all the programmes filter option selected from the add-on setings. filter_flag = 'lla=retliFnoissime'[::-1] menu_url = menu_url + '&csa=airetirc&1=redro?'[::-1] + filter_flag if all_programmes_flag and \ not filter_flag in menu_url else menu_url buffer_url = l.carga_web(menu_url) program_list = [] reset_cache = False curr_page_num = l.find_first(menu_url, page_num_pattern) or '1' if curr_page_num != '1': previous_page_url = l.find_first(buffer_url, page_url_pattern % 'Anterior') prev_page_num = l.find_first(previous_page_url, page_num_pattern) program_entry = { 'url' : root_url + previous_page_url.replace('&', '&'), 'title' : '<< %s (%s)' % (localized('Previous page'), prev_page_num), 'action' : 'program_list', } program_list.append(program_entry) reset_cache = True for program_section in buffer_url.split(program_section_sep)[1:]: date = l.find_first(program_section, program_fecha_pattern) desc = l.find_first(program_section, program_desc_pattern) url, title = l.find_first(program_section, program_link_pattern) or ('', '') genre = l.find_first(program_section, program_genre_pattern) canal = l.find_first(program_section, program_canal_pattern) title = get_clean_title(title) l.log('Program info. url: "%s" canal: "%s" title: "%s" genre: "%s" date: "%s"' % ( url, canal, title, genre, date)) program_entry = { 'url' : root_url + url, 'title' : "%s (%s | %s | %s)" % ( title, canal, genre, date, ), 'comment' : "%s\n%s - %s" % ( desc.strip(), genre, date, ), 'genre' : genre, 'canal' : canal, 'program' : title, 'action' : 'audio_list' } program_list.append(program_entry) last_page_num = l.find_first(buffer_url, page_num_url_pattern % 'Último') if last_page_num and curr_page_num != last_page_num: next_page_url = l.find_first(buffer_url, page_url_pattern % 'Siguiente') next_page_num = l.find_first(next_page_url, page_num_pattern) program_entry = { 'url' : root_url + next_page_url.replace('&', '&'), 'title' : '>> %s (%s/%s)' % ( localized('Next page'), next_page_num, last_page_num ), 'action' : 'program_list', } program_list.append(program_entry) return { 'program_list': program_list, 'reset_cache': reset_cache }
def get_search_list(search_url, localized=lambda x: x): """This function gets the list of items returned by the search engine.""" search_section_sep = '<div class="mediaBox audioBox "' search_link_pattern = '"src":"(http.*?mp3)"' search_title_pattern = '<span class="maintitle">([^<]*?)</span>' search_desc_pattern = '<div class="auxBox">[^<]*?<p>(.*?)</p>' search_dur_pattern = '<span class="duration">(.*?)</span>' hour_dur_pattern = '([0-9]+)h' min_dur_pattern = '([0-9.]+) min' search_year_pattern = '<span class="datpub">[0-9]+.[0-9]+.([0-9]+)</span>' page_url_pattern = '<li class="be_on"><span class="ico arrow %s_"><a href="([^"]*?)"' page_num_pattern = 'start=([0-9]+)' # Starts by 0 and the results goes from 10 to 10. search_root = '/rodacsub/se.evtr.www//:ptth'[::-1] buffer_url = l.carga_web(search_url) search_list = [] reset_cache = False previous_page_url = l.find_first(buffer_url, page_url_pattern % 'back') if previous_page_url: prev_page_num = int(l.find_first(previous_page_url, page_num_pattern))/10 + 1 search_entry = { 'url' : search_root + previous_page_url.replace('&', '&'), 'title' : '<< %s (%d)' % (localized('Previous page'), prev_page_num), 'action' : 'search_list', 'IsPlayable' : False } search_list.append(search_entry) reset_cache = True for search_section in buffer_url.split(search_section_sep)[1:]: duration = l.find_first(search_section, search_dur_pattern) H = l.find_first(duration, hour_dur_pattern) or '00' minutes = l.find_first(duration, min_dur_pattern) or '00' year = l.find_first(search_section, search_year_pattern) title = l.find_first(search_section, search_title_pattern).strip() desc = l.find_first(search_section, search_desc_pattern).strip() url = l.find_first(search_section, search_link_pattern) if '.' in minutes: M, S = (minutes[:2], minutes[3:5]) else: M, S = (minutes, '00') seconds = str(int(H) * 3600 + int(M) * 60 + int(S)) l.log('Podcast info. url: "%s" seconds: "%s" title: "%s"' % ( url, seconds, get_clean_title(title))) search_entry = { 'url' : url, 'title' : get_clean_title(title), 'comment' : get_clean_title(desc.replace('&', '&')), 'duration' : seconds, 'year' : year, 'action' : 'play_audio', 'IsPlayable' : True, } search_list.append(search_entry) next_page_url = l.find_first(buffer_url, page_url_pattern % 'next') if next_page_url: next_page_num = int(l.find_first(next_page_url, page_num_pattern))/10 + 1 search_entry = { 'url' : search_root + next_page_url.replace('&', '&'), 'title' : '>> %s (%d)' % (localized('Next page'), next_page_num), 'action' : 'search_list', 'IsPlayable' : False } search_list.append(search_entry) return { 'search_list': search_list, 'reset_cache': reset_cache }
def get_program_list(menu_url, all_programmes_flag=False, localized=lambda x: x): """This function makes programmes list data structure for all the program sections.""" program_pattern = '<dd><a title="([^"]*?)" href="([^"]*?)">[^<]*?</a></dd>' suffix = 'zaSP=ldom'[::-1] channel_pattern = '<span class="last">([^<]*?)</span></h1>' page_num_pattern = 'pbq=([0-9]+)' page_url_pattern = 'class="%s">.*?<a name="paginaIR" href="([^"]*?)"' last_page_sep = ' class="ultimo">' base_url_pattern = '(^[^?]*?)\?' suffix_pattern = '([^/]+)/$' suffix_string = 'zaSP=ldom&se=gnal&=adeuqsuBartel&s%=xtc&1=qbp?'[::-1] if not suffix in menu_url: suffix = suffix_string % l.find_first(menu_url, suffix_pattern) menu_url = menu_url + suffix buffer_url = l.carga_web(menu_url) program_list = [] reset_cache = False canal = l.find_first(buffer_url, channel_pattern) base_url = l.find_first(menu_url, base_url_pattern) curr_page_num = l.find_first(menu_url, page_num_pattern) or '1' if curr_page_num != '1': previous_page_url = l.find_first(buffer_url, page_url_pattern % 'anterior') prev_page_num = l.find_first(previous_page_url, page_num_pattern) program_entry = { 'url': base_url + previous_page_url.replace('&', '&'), 'title': '<< %s (%s)' % (localized('Previous page'), prev_page_num), 'action': 'program_list', } program_list.append(program_entry) reset_cache = True for title, url in l.find_multiple(buffer_url, program_pattern): l.log('Program info. url: "%s" canal: "%s" title: "%s"' % (url, canal, title)) program_entry = { 'url': url, 'title': title, 'comment': "", 'genre': "", 'canal': canal, 'program': title, 'action': 'audio_list' } program_list.append(program_entry) last_page_num = l.find_first( buffer_url.split(last_page_sep)[1], page_num_pattern) if last_page_sep in buffer_url else "" if last_page_num and curr_page_num != last_page_num: next_page_url = l.find_first(buffer_url, page_url_pattern % 'siguiente') next_page_num = l.find_first(next_page_url, page_num_pattern) program_entry = { 'url': base_url + next_page_url.replace('&', '&'), 'title': '>> %s (%s/%s)' % (localized('Next page'), next_page_num, last_page_num), 'action': 'program_list', } program_list.append(program_entry) return {'program_list': program_list, 'reset_cache': reset_cache}
def get_audio_list(program_url, localized=lambda x: x): """This function makes the emissions list data structure for all the programmes.""" audio_section_sep = '<span class="col_tit" ' audio_fecha_pattern = '<span class="col_fec">([^<]*?)</span>' audio_dur_pattern = '<span class="col_dur">([^<]*?)</span>' audio_title_pattern = '<span class="titulo-tooltip"><a href="[^"]*?" title="[^>]*?>([^<]*?)</a></span>' audio_desc_pattern = '<span class="detalle">(.*?)</span>' audio_link_pattern = '<span class="col_tip">.*?<a href="(http.*?mp[34])"' audio_rating_pattern = '<span class="col_pop"><span title="([^"]*?)" class="pc([0-9]*?)">' audio_year_pattern = '([0-9]{4})' page_num_pattern = 'pbq=([0-9]+)' last_page_sep = ' class="ultimo">' page_url_pattern = 'class="%s">.*?<a name="paginaIR" href="([^"]*?)"' url_options = ')ung-xunil(02%4.91.1F2%tegW=tnegA-resU|'[::-1] buffer_url = l.carga_web(program_url) audio_list = [] reset_cache = False this_year = l.get_this_year() curr_page_num = l.find_first(program_url, page_num_pattern) or '1' if curr_page_num != '1': previous_page_url = l.find_first(buffer_url, page_url_pattern % 'anterior') prev_page_num = l.find_first(previous_page_url, page_num_pattern) audio_entry = { 'url': root_url + previous_page_url.replace('&', '&').replace(' ', '%20'), 'title': '<< %s (%s)' % (localized('Previous page'), prev_page_num), 'action': 'audio_list', 'IsPlayable': False } audio_list.append(audio_entry) reset_cache = True else: first_page_url = l.find_first(buffer_url, page_url_pattern % 'primero') if not 'titleFilter' in first_page_url: audio_entry = { 'url': root_url + first_page_url.replace('&', '&') + '&titleFilter=%s', 'title': localized('Search'), 'action': 'search_program', 'IsPlayable': False } audio_list.append(audio_entry) for audio_section in buffer_url.split(audio_section_sep)[1:]: date = l.find_first(audio_section, audio_fecha_pattern) duration = l.find_first(audio_section, audio_dur_pattern) or '00:00:00' title = l.find_first(audio_section, audio_title_pattern) desc = l.find_first(audio_section, audio_desc_pattern) url = l.find_first(audio_section, audio_link_pattern) rtlabel, rating = l.find_first(audio_section, audio_rating_pattern) or ('', '1') year = int(l.find_first(date, audio_year_pattern) or '0') or this_year tduration = duration.split(':') if len(tduration) == 3: seconds = str( int(tduration[-3] or '0') * 3600 + int(tduration[-2] or '0') * 60 + int(tduration[-1] or '0')) elif len(tduration) == 2: seconds = str( int(tduration[-2] or '0') * 60 + int(tduration[-1] or '0')) else: seconds = tduration[-1] l.log( 'Podcast info. url: "%s" duration: "%s" seconds: "%s" title: "%s" rating: "%s" date: "%s"' % (url, duration, seconds, title, rating, date)) audio_entry = { 'url': url + url_options, 'title': "%s (%s)" % ( get_clean_title(title), date, ), 'comment': "%s\n%s - %s - %s" % ( get_clean_title(desc), duration, date, rtlabel, ), 'rating': int(rating) // 20, # Rating goes from 0 to 5 in audio media. 'duration': seconds, 'year': year, 'action': 'play_audio', 'IsPlayable': True, } if url: # This is to make sure the URL is valid. audio_list.append(audio_entry) last_page_num = l.find_first( buffer_url.split(last_page_sep)[1], page_num_pattern) if last_page_sep in buffer_url else "" if last_page_num and curr_page_num != last_page_num: next_page_url = l.find_first(buffer_url, page_url_pattern % 'siguiente') next_page_num = l.find_first(next_page_url, page_num_pattern) audio_entry = { 'url': root_url + next_page_url.replace('&', '&').replace(' ', '%20'), 'title': '>> %s (%s/%s)' % (localized('Next page'), next_page_num, last_page_num), 'action': 'audio_list', 'IsPlayable': False } audio_list.append(audio_entry) return {'audio_list': audio_list, 'reset_cache': reset_cache}
def main_list(params): lutil.log("esa.main_list "+repr(params)) # Loads the web page from ESA with the video list. page_url = params.get("url") reset_cache = params.get("reset_cache") genre = params.get("genre") buffer_web = lutil.carga_web(page_url) # Extract video items from the html content pattern_currentpage = '<span class="current">([^<]*?)</span>' pattern_page_url = '^%s([^\?]+)' pattern_nextpage = '<span class="next"><a href="([^"]*?)">' pattern_prevpage = '<span class="previous"><a href="([^"]*?)">' pattern_last = '<span class="other"><a href="[^"]*?">([^<]+)</a></span>' pattern_videos = '<div class="psr_item_grid">(.*?)</div>' pattern_videolink = '<a href="([^"]*?)"' pattern_thumbnail = '<img src="([^"]*?)"' pattern_title = '<span class="line2hell">([^<]+)</span>' pattern_date = '<span class="date">([^<]*?)</span>' pattern_year = '([0-9]{4})' lutil.set_content_list(pluginhandle, 'tvshows') lutil.set_plugin_category(pluginhandle, genre) page_current = lutil.find_first(buffer_web, pattern_currentpage) or '1' page_url_pref = lutil.find_first(page_url, pattern_page_url % root_url) # We must setup the previous page entry from the second page onwards. if page_current != '1': prev_page_url = lutil.find_first(buffer_web, pattern_prevpage) lutil.log('esa.main_list Value of current_page_url: "%s"' % page_url) prev_page_pref = lutil.find_first(prev_page_url, pattern_page_url % '') prev_page_url = page_url.replace(page_url_pref, prev_page_pref) reset_cache = "yes" lutil.addDir(action="main_list", title="<< %s (%s)" % (translation(30106), (int(page_current) - 1)), url=prev_page_url, reset_cache=reset_cache, genre=genre) # This is to force ".." option to go back to main index instead of previous page list. updateListing = reset_cache == "yes" videolist = lutil.find_multiple(buffer_web, pattern_videos) for video_entry in videolist: video_info = {} video_link = lutil.find_first(video_entry, pattern_videolink) thumbnail_link = lutil.find_first(video_entry, pattern_thumbnail) title = lutil.find_first(video_entry, pattern_title) title = title.replace('"', '"').replace(''', '´').replace('&', '&') # Cleanup the title. date = lutil.find_first(video_entry, pattern_date).strip().replace(' ', '') if date: video_info['Year'] = lutil.find_first(date, pattern_year) title = '%s (%s)' % (title, date) url = '%s%s' % (root_url, video_link) thumbnail = '%s%s' % (root_url, thumbnail_link) video_info['Genre'] = genre video_info['Plot'] = title # The description only appears when we load the link. lutil.log('esa.main_list Videolist: URL: "%s" Title: "%s" Thumbnail: "%s"' % (url, title, thumbnail)) # Appends a new item to the xbmc item list lutil.addLink(action="play_video", title=title, url=url, thumbnail=thumbnail, video_info=video_info, show_fanart=show_fanart) # Here we get the next page URL to add it at the end of the current video list page. next_page_url = lutil.find_first(buffer_web, pattern_nextpage) if next_page_url: next_page_pref = lutil.find_first(next_page_url, pattern_page_url % '') last_page = lutil.find_multiple(buffer_web, pattern_last)[-1] or '' lutil.log("esa.main_list Value of last_page: %s" % last_page) lutil.log('esa.main_list Value of current_page_url: "%s"' % page_url) next_page_url = page_url.replace(page_url_pref, next_page_pref) lutil.addDir(action="main_list", title=">> %s (%s/%s)" % (translation(30010), int(page_current) + 1, last_page), url=next_page_url, reset_cache=reset_cache, genre=genre) lutil.close_dir(pluginhandle, updateListing=updateListing)
def get_videolist(url, cat_menu=""): """This function gets the video list from the FFA website and returns them in a pretty data format.""" video_entry_sep = 'content-type-video' video_url_pattern = '["\'](/watch/[^/]*?/)' video_thumb_pattern = '["\'](/img/[^"\']*?)["\']' video_title_pattern = '<a href=["\']/watch/[^/]*?/["\'][ ]*?>([^<]+?)</a>' video_plot_pattern = '<span class="content-description">([^<]*?)</span>' video_duration_pattern = '([0-9]+[ ]+[Mm]in)' video_rating_pattern = '([0-9.]+[ ]+[Ss]tars)' video_views_pattern = '([0-9,]+[ ]+[Vv]iews)' page_num_pattern = 'href=["\']/library/([0-9]+)/' page_num_url_pattern = 'href=["\'](/library/%d/[^"\']*?)["\']' page_num_cur_pattern = '/library/([0-9]+)/' buffer_url = l.carga_web(url) video_list = [] reset_cache = False current_page_num = int(l.find_first(url, page_num_cur_pattern) or '1') last_page_num = int(max(l.find_multiple(buffer_url, page_num_pattern) or ('1',), key=int)) if current_page_num != 1: prev_page_num = current_page_num - 1 previous_page_url = root_url + l.find_first(buffer_url, page_num_url_pattern % prev_page_num) video_entry = { 'url': previous_page_url, 'title': '<< %s (%d)' % (cat_menu, prev_page_num), 'IsPlayable': False } video_list.append(video_entry) reset_cache = True category = "Video" # The category is no longer included in the latest website change. for video_section in buffer_url.split(video_entry_sep)[1:]: url = l.find_first(video_section, video_url_pattern) thumb = l.find_first(video_section, video_thumb_pattern) title = l.find_first(video_section, video_title_pattern) plot = l.find_first(video_section, video_plot_pattern) duration = l.find_first(video_section, video_duration_pattern) rating = l.find_first(video_section, video_rating_pattern) views = l.find_first(video_section, video_views_pattern) l.log('Video info. url: "%s" thumb: "%s" title: "%s"' % (url, thumb, title)) l.log('Video tags. duration: "%s" rating: "%s" views: "%s"' % (duration, rating, views)) video_entry = { 'url' : root_url + url, 'title' : title.strip() or '.', 'thumbnail' : root_url + thumb, 'plot' : "%s\n%s - %s - %s" % ( plot.strip(), duration, views, rating, ), 'duration' : int(duration.split()[0]) * 60 if duration else 0, 'rating' : rating.split()[0] if rating else '', 'genre' : category, 'IsPlayable' : True } video_list.append(video_entry) if current_page_num < last_page_num: next_page_num = current_page_num + 1 next_page_url = root_url + l.find_first(buffer_url, page_num_url_pattern % next_page_num) video_entry = { 'url': next_page_url, 'title': '>> %s (%d/%d)' % (cat_menu, next_page_num, last_page_num), 'IsPlayable': False } video_list.append(video_entry) return { 'video_list': video_list, 'reset_cache': reset_cache }
def get_playable_tagtele_url(tagtele_url): """This function returns the playable URL for the Tagtele embedded video from the video link retrieved.""" pattern_tagtele_video = " file: '(.+?)'" buffer_link = l.carga_web(tagtele_url) return l.find_first(buffer_link, pattern_tagtele_video)
def get_playable_kickstarter_url(kickstarter_url): """This function returns the playable URL for the Kickstarter embedded video from the video link retrieved.""" pattern_kickstarter_video = ' data-video-url="(.+?)"' buffer_link = l.carga_web(kickstarter_url) return l.find_first(buffer_link, pattern_kickstarter_video)
def get_playable_archiveorg_url(archive_url): """This function returns the playable URL for the Archive.org embedded video from the video link retrieved.""" pattern_archive_video = '<meta property="og:video" content="(.+?)"' buffer_link = l.carga_web(archive_url) return l.find_first(buffer_link, pattern_archive_video)