def play(url): iview_config = comm.get_config() auth = comm.get_auth(iview_config) p = classes.Program() p.parse_xbmc_url(url) try: # Playpath shoud look like this: # Akamai: mp4:flash/playback/_definst_/itcrowd_10_03_02 playpath = auth['playpath_prefix'] + p.url if playpath.split('.')[-1] == 'mp4': playpath = 'mp4:' + playpath # Strip off the .flv or .mp4 playpath = playpath.split('.')[0] # rtmp://cp53909.edgefcs.net/ondemand?auth=daEbjbeaCbGcgb6bedYacdWcsdXc7cWbDda-bmt0Pk-8-slp_zFtpL&aifp=v001 # playpath=mp4:flash/playback/_definst_/kids/astroboy_10_01_22 swfurl=http://www.abc.net.au/iview/images/iview.jpg swfvfy=true rtmp_url = "%s?auth=%s playpath=%s swfurl=%s swfvfy=true" % (auth['rtmp_url'], auth['token'], playpath, config.swf_url) listitem=xbmcgui.ListItem(label=p.get_list_title(), iconImage=p.thumbnail, thumbnailImage=p.thumbnail) listitem.setInfo('video', p.get_xbmc_list_item()) xbmc.Player().play(rtmp_url, listitem) except: # oops print error message d = xbmcgui.Dialog() message = utils.dialog_error("Unable to play video") d.ok(*message) utils.log_error();
def play(url): try: addon = xbmcaddon.Addon() p = classes.Program() p.parse_xbmc_url(url) # Some programs don't have protected streams. 'Public' streams are # set in program.url, otherwise we fetch it separately if p.get_url(): stream_info = {} stream_url = p.get_url() else: stream_info = comm.get_stream(p.id) stream_url = stream_info['url'] bandwidth = addon.getSetting('BANDWIDTH') if bandwidth == '0': stream_url = stream_url.replace('&b=0-2000', '&b=400-600') elif bandwidth == '1': stream_url = stream_url.replace('&b=0-2000', '&b=900-1100') elif bandwidth == '2': stream_url = stream_url.replace('&b=0-2000', '&b=1400-1600') listitem = xbmcgui.ListItem(label=p.get_list_title(), iconImage=p.thumbnail, thumbnailImage=p.thumbnail, path=stream_url) listitem.setInfo('video', p.get_kodi_list_item()) # Add subtitles if available if 'subtitles' in stream_info: sub_url = stream_info['subtitles'] profile = addon.getAddonInfo('profile') path = xbmc.translatePath(profile).decode('utf-8') if not os.path.isdir(path): os.makedirs(path) subfile = xbmc.translatePath( os.path.join(path, 'subtitles.eng.srt')) if os.path.isfile(subfile): os.remove(subfile) try: data = urllib2.urlopen(sub_url).read() f = open(subfile, 'w') f.write(data) f.close() if hasattr(listitem, 'setSubtitles'): # This function only supported from Kodi v14+ listitem.setSubtitles([subfile]) except Exception: utils.log('Subtitles not available for this program') if hasattr(listitem, 'addStreamInfo'): listitem.addStreamInfo('audio', p.get_kodi_audio_stream_info()) listitem.addStreamInfo('video', p.get_kodi_video_stream_info()) xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, listitem=listitem) except Exception: utils.handle_error("Unable to play video")
def play(url): try: p = classes.Program() p.parse_xbmc_url(url) listitem = xbmcgui.ListItem(label=p.get_list_title(), iconImage=p.thumbnail, thumbnailImage=p.thumbnail, path="%s|X-Forwarded-For=101.188.88.88" % p.get_url()) listitem.setInfo('video', p.get_xbmc_list_item()) #add subtitles if available addon = xbmcaddon.Addon(config.ADDON_ID) subtitles = None if addon.getSetting('subtitles_enabled') == 'true': profile = xbmcaddon.Addon().getAddonInfo('profile') path = xbmc.translatePath(profile).decode('utf-8') if not os.path.isdir(path): os.makedirs(path) subfile = xbmc.translatePath( os.path.join(path, 'subtitles.eng.srt')) if os.path.isfile(subfile): os.remove(subfile) suburl = (config.subtitle_url + p.url[p.url.rfind('/') + 1:p.url.rfind('_')] + '.xml') try: data = urllib2.urlopen(suburl).read() f = open(subfile, 'w') f.write(parse.convert_to_srt(data)) f.close() if hasattr(listitem, 'setSubtitles'): # This function only supported from Kodi v14+ listitem.setSubtitles([subfile]) else: subtitles = True except: utils.log('Subtitles not available for this program') if hasattr(listitem, 'addStreamInfo'): listitem.addStreamInfo('audio', p.get_xbmc_audio_stream_info()) listitem.addStreamInfo('video', p.get_xbmc_video_stream_info()) xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, listitem=listitem) # Enable subtitles for XBMC v13 if addon.getSetting('subtitles_enabled') == "true": if subtitles == True: if not hasattr(listitem, 'setSubtitles'): player = xbmc.Player() while not player.isPlaying(): xbmc.sleep(100) # wait until video is being played player.setSubtitles(subfile) except: utils.handle_error("Unable to play video")
def play(url): try: # Remove cookies.dat for Kodi < 17.0 - causes issues with playback cookies_dat = xbmc.translatePath('special://home/cache/cookies.dat') if os.path.isfile(cookies_dat): os.remove(cookies_dat) p = classes.Program() p.parse_xbmc_url(url) stream = comm.get_stream_url(p.get_house_number(), p.get_url()) listitem = xbmcgui.ListItem(label=p.get_list_title(), iconImage=p.thumbnail, thumbnailImage=p.thumbnail, path=stream) listitem.setInfo('video', p.get_kodi_list_item()) # Add subtitles if available addon = xbmcaddon.Addon() if addon.getSetting('subtitles_enabled') == 'true': profile = xbmcaddon.Addon().getAddonInfo('profile') path = xbmc.translatePath(profile).decode('utf-8') if not os.path.isdir(path): os.makedirs(path) subfile = xbmc.translatePath( os.path.join(path, 'subtitles.eng.srt')) if os.path.isfile(subfile): os.remove(subfile) try: data = urllib2.urlopen(p.subtitle_url).read() f = open(subfile, 'w') f.write(parse.convert_to_srt(data)) f.close() listitem.setSubtitles([subfile]) except Exception: utils.log('Subtitles not available for this program') if hasattr(listitem, 'addStreamInfo'): listitem.addStreamInfo('audio', p.get_kodi_audio_stream_info()) listitem.addStreamInfo('video', p.get_kodi_video_stream_info()) xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, listitem=listitem) except Exception: utils.handle_error('Unable to play video')
def play(url): try: iview_config = comm.get_config() auth = comm.get_auth(iview_config) # We don't support Adobe HDS yet, Fallback to RTMP streaming server if auth['rtmp_url'].startswith('http://'): auth['rtmp_url'] = iview_config[ 'rtmp_url'] or config.akamai_fallback_server auth['playpath_prefix'] = config.akamai_playpath_prefix utils.log("Adobe HDS Not Supported, using fallback server %s" % auth['rtmp_url']) p = classes.Program() p.parse_xbmc_url(url) # Playpath shoud look like this: # Akamai: mp4:flash/playback/_definst_/itcrowd_10_03_02 playpath = auth['playpath_prefix'] + p.url if playpath.split('.')[-1] == 'mp4': playpath = 'mp4:' + playpath # Strip off the .flv or .mp4 playpath = playpath.split('.')[0] # rtmp://cp53909.edgefcs.net/ondemand?auth=daEbjbeaCbGcgb6bedYacdWcsdXc7cWbDda-bmt0Pk-8-slp_zFtpL&aifp=v001 # playpath=mp4:flash/playback/_definst_/kids/astroboy_10_01_22 swfurl=http://www.abc.net.au/iview/images/iview.jpg swfvfy=true rtmp_url = "%s?auth=%s playpath=%s swfurl=%s swfvfy=true" % ( auth['rtmp_url'], auth['token'], playpath, config.swf_url) listitem = xbmcgui.ListItem(label=p.get_list_title(), iconImage=p.thumbnail, thumbnailImage=p.thumbnail) listitem.setInfo('video', p.get_xbmc_list_item()) if hasattr(listitem, 'addStreamInfo'): listitem.addStreamInfo('audio', p.get_xbmc_audio_stream_info()) listitem.addStreamInfo('video', p.get_xbmc_video_stream_info()) xbmc.Player().play(rtmp_url, listitem) except: # oops print error message d = xbmcgui.Dialog() message = utils.dialog_error("Unable to play video") d.ok(*message) utils.log_error()
def get_program(program_id): """ Fetch the program information and streaming URL for a given program ID """ try: brightcove_url = "https://api.brightcove.com/services/library?command=find_video_by_reference_id&reference_id=%s&media_delivery=HTTP_IOS&video_fields=id,name,shortDescription,videoStillURL,length,FLVURL&token=BMG-nlpt1dDQcdqz-EIBAUNRGtXnLQv-gbltLyHgproxck0YUZfnkA.." % program_id data = fetch_url(brightcove_url) except: raise Exception( "Error fetching program information, possibly unavailable.") if data == 'null': utils.log("Brightcove returned: '%s'" % data) raise Exception( "Error fetching program information, possibly unavailable.") try: program_data = json.loads(data) except: utils.log("Bad program data: %s" % program_data) raise Exception("Error decoding program information.") program = classes.Program() program.id = program_data['id'] program.title = program_data['name'] program.description = program_data['shortDescription'] program.thumbnail = program_data['videoStillURL'] if addon and addon.getSetting( 'video_transport') == 'Native mode (v13 Gotham)': # Use Apple iOS HLS stream directly # This requires gnutls support in ffmpeg, which is only found in XBMC v13 # but not available at all in iOS or Android builds utils.log("Using native HTTPS HLS stream handling...") program.url = program_data['FLVURL'] else: # Use Adam M-W's implementation of handling the HTTPS business within # the m3u8 file directly. He's a legend. utils.log("Using stream compatibility mode...") program.url = get_m3u8(program_data['id']) return program
def play(url): addon = xbmcaddon.Addon(config.ADDON_ID) try: p = classes.Program() p.parse_xbmc_url(url) listitem = xbmcgui.ListItem(label=p.get_list_title(), iconImage=p.thumbnail, thumbnailImage=p.thumbnail) listitem.setInfo('video', p.get_xbmc_list_item()) if hasattr(listitem, 'addStreamInfo'): listitem.addStreamInfo('audio', p.get_xbmc_audio_stream_info()) listitem.addStreamInfo('video', p.get_xbmc_video_stream_info()) xbmc.Player().play(p.get_url(), listitem) except: utils.handle_error("Unable to play video")
def application2_programm(path): wb = openpyxl.load_workbook(path) # 'Приложение №2.xlsx' programms = [] sheet = wb['параметры программ'] out = sheet['B2'].value for i in range(2, 41): x_ = sheet['B{}'.format(i)].value if x_: out = x_.replace('\n', ' ') programms.append( classes.Program( sheet['A{}'.format(i)].value, out, sheet['C{}'.format(i)].value, sheet['D{}'.format(i)].value, sheet['E{}'.format(i)].value, sheet['F{}'.format(i)].value, sheet['G{}'.format(i)].value, sheet['H{}'.format(i)].value, sheet['I{}'.format(i)].value, sheet['J{}'.format(i)].value, sheet['K{}'.format(i)].value, sheet['L{}'.format(i)].value, sheet['M{}'.format(i)].value)) return programms
def play(url): params = utils.get_url(url) p = classes.Program() p.parse_xbmc_url(url) program_id = comm.get_program_id(params['url_path']) stream = comm.get_stream(program_id) # Plus7 has returned a specific error if stream.has_key('error'): d = xbmcgui.Dialog() msg = utils.dialog_message("Unable to play video:\n%s" % stream['error']) d.ok(*msg) return try: # RTMP URL isn't available if stream.has_key('rtmp_host'): # Build the final RTMP Url. New syntax for external librtmp # http://trac.xbmc.org/ticket/8971 rtmp_url = "%s playpath=%s swfurl=%s swfvfy=true" % ( stream['rtmp_host'], stream['rtmp_path'], config.swf_url) listitem = xbmcgui.ListItem(label=p.title, iconImage=p.thumbnail, thumbnailImage=p.thumbnail) listitem.setInfo('video', p.get_xbmc_list_item()) xbmc.Player().play(rtmp_url, listitem) else: d = xbmcgui.Dialog() msg = utils.dialog_message( "Unable to play video:\nStream URL not found.") d.ok(*msg) return except: # oops print error message d = xbmcgui.Dialog() message = utils.dialog_error("Unable to play video") d.ok(*message) utils.log_error()
def get_program(program_id): """ Fetch the program information and streaming URL for a given program ID """ brightcove_url = "https://api.brightcove.com/services/library?command=find_video_by_reference_id&reference_id=%s&media_delivery=HTTP_IOS&video_fields=id,name,shortDescription,videoStillURL,length,FLVURL&token=BMG-nlpt1dDQcdqz-EIBAUNRGtXnLQv-gbltLyHgproxck0YUZfnkA.." % program_id data = fetch_url(brightcove_url) program_data = json.loads(data) program = classes.Program() program.id = program_data['id'] program.title = program_data['name'] program.description = program_data['shortDescription'] program.thumbnail = program_data['videoStillURL'] # Apple iOS HLS stream program.url = program_data['FLVURL'] # High-quality WMV - doesn't play after about 10 seconds #program.url = program_data['WVMRenditions'][-1]['url'] return program
def parse_programs_from_feed(data, episode_count): jsondata = json.loads(data) related = config.FEED_URL.format(jsondata['related']) programs_list = [] related_list = [] related_list.append(jsondata) if int(episode_count) > 1: comm.fetch_related_list(parse_other_episodes(related), related_list) for item in related_list: if 'playlist' not in item: continue p = classes.Program() title = item.get('seriesTitle') p.title = title # Convoluted Season/Episode parsing title_match = None title_parts = None subtitle = item.get('title') if subtitle: # Series 2 Episode 25 Home Is Where The Hatch Is # Series 4 Ep:11 As A Yoga Yuppie # Series 4 Ep 10: Emission Impossible title_match = re.search( '^[Ss]eries\s?(?P<series>\w+):?\s[Ee]p(isode)?:?\s?(?P<episode>\d+):?\s(?P<episode_title>.*)$', subtitle) # noqa if not title_match: # Series 8 Episode 13 # Series 8 Episode:13 title_match = re.search( '^[Ss]eries\s?(?P<series>\w+):?\s?[Ee]p(isode)?:?\s?(?P<episode>\d+)$', subtitle) # noqa if not title_match: # Episode 34 Shape Shifter # Ep:34 Shape Shifter title_match = re.search( '^[Ee]p(isode)?:?\s?(?P<episode>\d+):?\s?(?P<episode_title>.*)$', subtitle) # noqa if not title_match: # Series 10 Rylan Clark, Joanna Lumley, Ant And Dec title_match = re.search( '^[Ss]eries:?\s?(?P<series>\d+):?\s(?P<episode_title>.*)$', subtitle) # noqa if not title_match: # Episode 5 # Ep 5 # Episode:5 title_match = re.search('^[Ee]p(isode)?:?\s?(?P<episode>\d+)$', subtitle) if not title_match: p.episode_title = subtitle if title_match: title_parts = title_match.groupdict() p.episode_title = title_parts.get('episode_title') try: # If we only get series/episode in the subtitle p.series = title_parts.get('series') p.episode = title_parts.get('episode') except Exception: pass p.house_number = item.get('episodeHouseNumber') p.description = item.get('description') p.thumbnail = item.get('thumbnail') addon = xbmcaddon.Addon() if ('hls-plus' in item['playlist'][-1] and addon.getSetting('hd_streams') == 'true'): p.url = item['playlist'][-1]['hls-plus'] p.hq = True else: p.url = item['playlist'][-1]['hls-high'] p.rating = item.get('rating') p.duration = item.get('duration') try: p.subtitle_url = item['playlist'][-1]['captions']['src-vtt'] except Exception: pass p.date = get_datetime(item.get('pubDate')) p.expire = get_datetime(item.get('expireDate')) programs_list.append(p) sorted_programs = sorted(programs_list, key=lambda x: x.get_date_time(), reverse=True) return sorted_programs
def parse_programs_from_feed(data): xml = ET.fromstring(data) programs_list = [] for item in xml.getiterator('item'): p = classes.Program() title = item.find('title').text p.title = title subtitle = item.find('subtitle').text title_match = None title_parts = None if subtitle: # Series 2 Episode 25 Home Is Where The Hatch Is title_match = re.search('^[Ss]eries\s?(?P<series>\w+)\s[Ee]p(isode)?\s?(?P<episode>\d+)\s(?P<episode_title>.*)$', subtitle) if not title_match: # Series 8 Episode 13 title_match = re.search('^[Ss]eries\s?(?P<series>\w+)\s[Ee]p(isode)?\s?(?P<episode>\d+)$', subtitle) if not title_match: # Episode 34 Shape Shifter title_match = re.search('^[Ee]p(isode)?\s?(?P<episode>\d+)\s(?P<episode_title>.*)$', subtitle) if not title_match: # Series 10 Rylan Clark, Joanna Lumley, Ant And Dec, The Vaccines title_match = re.search('^[Ss]eries\s?(?P<series>\d+)\s(?P<episode_title>.*)$', subtitle) if not title_match: # Episode 5 title_match = re.search('^[Ee]p(isode)?\s?(?P<episode>\d+)$', subtitle) if not title_match: p.episode_title = subtitle if title_match: title_parts = title_match.groupdict() p.episode_title = title_parts.get('episode_title') try: # If we have actual series/episode fields given p.series = item.find('series').text p.episode = item.find('episode').text except: try: # If we only get series/episode in the subtitle p.series = title_parts.get('series') p.episode = title_parts.get('episode') except: pass p.description = item.find('description').text p.url = item.find('{http://www.abc.net.au/tv/mrss}videoAsset').text p.thumbnail = item.find('{http://search.yahoo.com/mrss/}thumbnail').attrib['url'] try: p.rating = item.find('{http://www.abc.net.au/tv/mrss}rating').text except: # Rating not given for all programs pass try: duration = item.find('{http://search.yahoo.com/mrss/}content').attrib['duration'] p.duration = int(duration) except: utils.log("Couldn't parse program duration: %s" % duration) p.date = utils.get_datetime(item.find('pubDate').text) p.expire = utils.get_datetime(item.find('{http://www.abc.net.au/tv/mrss}expireDate').text) programs_list.append(p) return programs_list
def create_program(jd): p = classes.Program() p.id = jd['id'].split('/')[-1] # ID on the end of URL p.subfilename = jd.get('pl1$pilatId') p.title = jd.get('pl1$programName') if not p.title: p.title = jd.get('title') p.episode_title = jd.get('pl1$episodeTitle') try: p.series = int(jd.get('pl1$season')) p.episode = int(jd.get('pl1$episodeNumber')) except Exception: pass # If no other metadata available (mostly news), then use the # regular title, which probably includes the date if not p.series and not p.episode and not p.episode_title: p.title = jd.get('title') try: aired = int(jd.get('pubDate')) / 1000 p.date = datetime.datetime.fromtimestamp(aired) except Exception: pass try: expire = int(jd.get('media$expirationDate')) / 1000 p.expire = datetime.datetime.fromtimestamp(expire) except Exception: pass p.description = jd.get('pl1$shortSynopsis') if not p.description: p.description = jd.get('description') p.thumbnail = jd.get('thumbnail') if not p.thumbnail: for image in jd['media$thumbnails']: if 'Thumbnail Large' in image['plfile$assetTypes']: p.thumbnail = image['plfile$downloadUrl'] break if 'media$content' in jd: # Sort media content by bitrate, highest last content_list = sorted(jd['media$content'], key=lambda k: k['plfile$bitrate']) content = content_list[-1] try: p.duration = int(float(content.get('plfile$duration'))) except Exception: utils.log("Failed to parse duration: %s" % content.get('plfile$duration')) # Some shows, mostly clips aren't protected if 'Public' in content['plfile$assetTypes']: p.url = content['plfile$downloadUrl'] else: utils.log("No 'media$content' found for %s" % p.title) return p
def get_series(series_id): """ <li class="clearfix"> <a href="/plus7/felix-the-cat/-/watch/12698938/getting-rid-of-sniffer-series-1-episode-9/?play=1" class="vidimg"> <img class="listimg" src="http://l.yimg.com/ea/img/-/120123/kids_felix_s1ep9_lrg_17hqg69-17hqg6o.jpg?x=118&y=66&xc=1&yc=2&wc=629&hc=352&sig=9aw7XqRoa4GRA2aCvHR2GQ--" alt="Felix The Cat" /> <span class="vidimg-play"> <span class="txt">Play Video</span> <span class="matte"></span> </span> </a> <div class="itemdetails"> <h3><a href="/plus7/felix-the-cat/-/watch/12698938/getting-rid-of-sniffer-series-1-episode-9/"> <span class="title">Felix The Cat</span> <span class="subtitle"> Getting Rid of Sniffer, series 1 episode 9</span> </a></h3> <p>Rock Bottom and the Professor need $10,000 for a vacation, which Felix won't lend them.</p> </div> <a class="myshows-link" rel="autv-plus7-felix-the-cat"></a> </li> """ program_list = [] url = config.series_url % series_id data = fetch_url(url) data = data.replace('\n', '') #title = re.findall(r'<h2>(.*?)</h2>', data)[0] programs_data = re.findall( r'<ul id="related-episodes" class="featlist">(.*?)</ul>', data)[0] # ['John Safran's Race Relations', 'John Safran's Race Relations'] titles = re.findall(r'<span class="title">(.*?)</span>', programs_data) # ['Episode desc', 'Episode desc'] descs = re.findall(r'<p>(.*?)</p>', programs_data) # [' Wed 14 July, series 4 episode 2', ' Wed 14 July, series 4 episode 1'] subtitles = re.findall(r'<span class="subtitle">(.*?)</span>', programs_data) # ['http://l.yimg.com/ea/img/-/100714/0714_city_homicide_ep56v2_sml-163qgka.jpg', 'http://l.yimg.com/ea/img/-/100714/0714_city_homicide_ep55v2_sml-163qgjl.jpg'] thumbs = re.findall(r'<img class="listimg" src="(.*?)\?', programs_data) # ['/plus7/city-homicide/-/watch/7583800/wed-14-july-series-4-episode-2/', '/plus7/city-homicide/-/watch/7583794/wed-14-july-series-4-episode-1/'] urls = re.findall(r'<h3><a href="(.*?)">', programs_data) num_episodes = len(urls) for i in xrange(num_episodes): program = classes.Program() program.title = titles[i] program.description = descs[i] program.thumbnail = thumbs[i] program.url_path = urls[i] # Subtitle can be any one of: # Sun 18 Mar, series 3 episode 30 # Sun 18 March, series 3 episode 30 # Dragon Invasion, series 1 episode 9 # Now on Sundays # Conan O'Brian, 2001 sub_split = subtitles[i].split(',') for sub in sub_split: # Strip the stupid spacing either side sub = sub.lstrip(" ").rstrip(" ") # Convert to python compatible short day sub = sub.replace("Tues ", "Tue ") sub = re.sub("March$", "Mar", sub) # Not a date - check for episode/series episode = re.search('[Ee]pisode\s?(?P<episode>\d+)', sub) if episode: program.episode = int(episode.group('episode')) #utils.log("Episode found: '%s'" % program.episode) # Only check for series if we've previously found episode series = re.search('[Ss]eries\s?(?P<series>\w+)', sub) if series: program.season = int(series.group('series')) #utils.log("Season found: '%s'" % program.season) else: try: # Try parsing the date date = "%s %s" % (sub, program.get_year()) timestamp = time.mktime(time.strptime(date, '%a %d %b %Y')) program.date = datetime.date.fromtimestamp(timestamp) #utils.log("Date found: '%s'" % program.date) except: # Occasionally, we have Series X, Episode X with the comma series = re.search('[Ss]eries\s?(?P<series>\w+)', sub) if series: program.season = int(series.group('series')) #utils.log("Season found: '%s'" % program.season) else: # Not a date or contains 'episode' - must be title if sub != '': # Sometimes the actual title has a comma in it. We'll just reconstruct # the parts in that case if program.episode_title: program.episode_title = "%s, %s" % ( program.episode_title, sub) else: program.episode_title = sub #utils.log("Episode title found: '%s'" % program.episode_title) program_list.append(program) return program_list
def p_program(p): """program : instructions_opt""" p[0] = classes.Program(p[1])
def get_program(path): """ This isn't being used right now. It was previously used to pull more metadata for programs, but meant that we have to make a new http request for every episode listing, which was too slow. """ index = fetch_url(config.program_url + path) program = classes.Program() program.id = re.findall("vid : '(.*?)'", index)[0] program.title = re.findall("<h1>(.*?)</h1>", index)[0] try: program.category = re.findall("Genre: <strong>(.*?)</strong>", index)[0] except: utils.log_error("Unable to parse program category") try: # Classified is now seperated by a newline program.rating = re.findall("Classified:\s\s+<strong>(.*?)</strong>", index, re.DOTALL)[0] except: utils.log_error("Unable to parse program classification") # Get the URL, but split it from the '?', to get the high-res image try: program.thumbnail = re.findall('<img class="listimg" src="(.*?)" alt', index)[0].split("?")[0] except: print "Unable to find thumbnail" # Get metadata. URL looks like: # http://cosmos.bcst.yahoo.com/rest/v2/pops;id=%s;lmsoverride=1 url = config.program_metadata_url % program.id index = fetch_url(url) try: program.episode_title = re.findall( "<title><!\[CDATA\[(.*?)\]\]></title>", index)[0].split(": ")[1] except: utils.log_error("Unable to parse episode title") try: program.description = re.findall( "<description><!\[CDATA\[(.*?)\]\]></description>", index)[0] except: utils.log_error("Unable to parse episode description") try: program.thumbnail = re.findall( '<media:content medium="image" url="(.*?)" name=', index)[0] except: utils.log_error("Unable to parse program thumbnail") # Parsing the date is a nightmare date_string = re.findall( "<media:pubStart><!\[CDATA\[(.*?)\]\]></media:pubStart>", index)[0] # Convert to python compatible short day date_string = date_string.replace("Tues", "Tue") date_parts = date_string.split() try: date_without_tz = " ".join(date_parts[:-1]) timestamp = time.mktime( time.strptime(date_without_tz, '%m/%d/%Y %I:%M:%S %p')) # 05/18/2011 04:30:00 AM program.date = datetime.date.fromtimestamp(timestamp) except: date_without_tz = " ".join(date_parts[:-2]) timestamp = time.mktime( time.strptime(date_without_tz, '%m/%d/%Y %I:%M:%S')) # 05/18/2011 04:30:00 AM program.date = datetime.date.fromtimestamp(timestamp) return program
def parse_programs_from_feed(data): xml = ET.fromstring(data) programs_list = [] for item in xml.getiterator('item'): p = classes.Program() title = item.find('title').text p.title = title subtitle = item.find('subtitle').text title_match = None title_parts = None if subtitle: # Series 2 Episode 25 Home Is Where The Hatch Is title_match = re.search('^[Ss]eries\s?(?P<series>\w+)\s[Ee]pisode\s?(?P<episode>\d+)\s(?P<episode_title>.*)$', subtitle) if not title_match: # Series 8 Episode 13 title_match = re.search('^[Ss]eries\s?(?P<series>\w+)\s[Ee]pisode\s?(?P<episode>\d+)$', subtitle) if not title_match: # Episode 34 Shape Shifter title_match = re.search('^[Ee]pisode\s?(?P<episode>\d+)\s(?P<episode_title>.*)$', subtitle) if not title_match: # Series 10 Rylan Clark, Joanna Lumley, Ant And Dec, The Vaccines title_match = re.search('^[Ss]eries\s?(?P<series>\d+)\s(?P<episode_title>.*)$', subtitle) if not title_match: # Episode 5 title_match = re.search('^[Ee]pisode\s?(?P<episode>\d+)$', subtitle) if not title_match: p.episode_title = subtitle if title_match: title_parts = title_match.groupdict() p.episode_title = title_parts.get('episode_title') try: # If we have actual series/episode fields given p.series = item.find('series').text p.episode = item.find('episode').text except: try: # If we only get series/episode in the subtitle p.series = title_parts.get('series') p.episode = title_parts.get('episode') except: pass p.description = item.find('description').text p.url = item.find('{http://www.abc.net.au/tv/mrss}videoAsset').text p.thumbnail = item.find('{http://search.yahoo.com/mrss/}thumbnail').attrib['url'] try: p.rating = item.find('{http://www.abc.net.au/tv/mrss}rating').text except: # Rating not given for all programs pass try: duration = item.find('{http://search.yahoo.com/mrss/}content').attrib['duration'] p.duration = int(duration) except: utils.log("Couldn't parse program duration: %s" % duration) # Tue, 05 Aug 2014 14:45:00 +1000 pubdate = item.find('pubDate').text try: # Tue, 05 Aug 2014 14:45:00 +1000 pubdate = item.find('pubDate').text # strptime sucks. Remove the +1000 part from the end pubdate = re.sub(r' [+-]([0-9]){4}$', '', pubdate) dt = time.mktime(time.strptime(pubdate, '%a, %d %b %Y %H:%M:%S')) p.date = datetime.date.fromtimestamp(dt) except: utils.log("Couldn't parse program date: %s" % pubdate) programs_list.append(p) return programs_list
def play(url): try: # Remove cookies.dat for Kodi < 17.0 - causes issues with playback addon = xbmcaddon.Addon() cookies_dat = xbmc.translatePath('special://home/cache/cookies.dat') if os.path.isfile(cookies_dat): os.remove(cookies_dat) p = classes.Program() p.parse_xbmc_url(url) stream = comm.get_stream_url(p.get_house_number(), p.get_url()) use_ia = addon.getSetting('use_ia') == 'true' if use_ia: if addon.getSetting('ignore_drm') == 'false': try: import drmhelper if not drmhelper.check_inputstream(drm=False): return except ImportError: utils.log("Failed to import drmhelper") utils.dialog_message( 'DRM Helper is needed for inputstream.adaptive ' 'playback. Disable "Use inputstream.adaptive for ' 'playback" in settings or install drmhelper. For ' 'more information, please visit: ' 'http://aussieaddons.com/drm') return hdrs = stream[stream.find('|') + 1:] listitem = xbmcgui.ListItem(label=p.get_list_title(), iconImage=p.thumbnail, thumbnailImage=p.thumbnail, path=stream) if use_ia: listitem.setProperty('inputstreamaddon', 'inputstream.adaptive') listitem.setProperty('inputstream.adaptive.manifest_type', 'hls') listitem.setProperty('inputstream.adaptive.stream_headers', hdrs) listitem.setProperty('inputstream.adaptive.license_key', stream) listitem.setInfo('video', p.get_kodi_list_item()) # Add subtitles if available if p.subtitle_url: profile = xbmcaddon.Addon().getAddonInfo('profile') path = xbmc.translatePath(profile).decode('utf-8') if not os.path.isdir(path): os.makedirs(path) subfile = xbmc.translatePath( os.path.join(path, 'subtitles.eng.srt')) if os.path.isfile(subfile): os.remove(subfile) try: webvtt_data = urllib2.urlopen( p.subtitle_url).read().decode('utf-8') if webvtt_data: with open(subfile, 'w') as f: webvtt_subtitle = WebVTTReader().read(webvtt_data) srt_subtitle = SRTWriter().write(webvtt_subtitle) srt_unicode = srt_subtitle.encode('utf-8') f.write(srt_unicode) if hasattr(listitem, 'setSubtitles'): listitem.setSubtitles([subfile]) except Exception as e: utils.log( 'Subtitles not available for this program {0}'.format(e)) if hasattr(listitem, 'addStreamInfo'): listitem.addStreamInfo('audio', p.get_kodi_audio_stream_info()) listitem.addStreamInfo('video', p.get_kodi_video_stream_info()) xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, listitem=listitem) except Exception: utils.handle_error('Unable to play video')
def get_series(series_id): """ Fetch the episode list for a given series ID """ program_list = [] data = api_query( "select * from plus7 where key = '%s' and device = 'ios'" % series_id) json_data = json.loads(data) program_data = json_data['query']['results']['json']['episodes'] # For single programs, we'll need to force the output to be # list of dicts. if type(program_data) == dict: program_data = [program_data] for program in program_data: p = classes.Program() p.id = program['id'] p.title = program['show'] p.description = program['abstract'] p.thumbnail = program['image'] p.duration = int(float(program['duration'])) # Sometimes they leave out the episode information if program.has_key('episode') and program['episode'] is not None: episode = program['episode'] else: episode = program['show'] # Subtitle can be any one of: # Sun 18 Mar, series 3 episode 30 # Sun 18 March, series 3 episode 30 # Dragon Invasion, series 1 episode 9 # Beyond The Blacklist - Episode 12 # Now on Sundays # Conan O'Brian, 2001 # Replace any MS Word 'dash' instances episode = episode.replace(u'\u2013', u'-') # Sometimes they embed unicode episode = episode.encode('ascii', 'ignore') # Sometimes they separate with a dash episode = episode.replace(' - ', ' , ') sub_split = episode.split(',') for sub in sub_split: utils.log("Testing for episode title: %s" % sub) # Strip the stupid spacing either side sub = sub.lstrip(" ").rstrip(" ") # Convert to python compatible short day sub = sub.replace("Tues ", "Tue ") sub = sub.replace("Thurs ", "Thu ") sub = re.sub("March$", "Mar", sub) # Not a date - check for episode/series episode = re.search('[Ee]pisode\s?(?P<episode>\d+)', sub) if episode: try: p.episode = int(episode.group('episode')) utils.log("%s - Episode found: '%s'" % (sub, p.episode)) except: pass # Not a number. Move on. # Only check for series if we've previously found episode series = re.search('[Ss](eries|eason)\s?(?P<series>\w+)', sub) if series: try: p.season = int(series.group('series')) utils.log("%s - Season found: '%s'" % (sub, p.season)) except: pass # Not a number. Move on. else: try: # Try parsing the date date = "%s %s" % (sub, p.get_year()) timestamp = time.mktime(time.strptime(date, '%a %d %b %Y')) p.date = datetime.date.fromtimestamp(timestamp) utils.log("%s - Date found: '%s'" % (sub, p.date)) except: # Not a date or contains 'episode' - must be title if sub != '': # Sometimes the actual title has a comma in it. We'll just reconstruct # the parts in that case if p.episode_title: p.episode_title = "%s, %s" % (p.episode_title, sub) else: p.episode_title = sub utils.log("%s - Episode title found: '%s'" % (sub, p.episode_title)) program_list.append(p) return program_list
def parse_series_items(soup): series_json = json.loads(soup) programs_list = [] series_id = series_json[0]['a'] # Roary The Racing Car Series 2 series_title = series_json[0]['b'] series_thumb = series_json[0]['d'] for item in series_json[0]['f']: new_program = classes.Program() new_program.id = item.get('a') # Let's try and parse the title apart title_string = item.get('b') # Roary The Racing Car Series 2 Episode 25 Home Is Where The Hatch Is title_match = re.search( '^(?P<title>.*)\s+[Ss]eries\s?(?P<series>\w+)\s[Ee]pisode\s?(?P<episode>\d+)\s(?P<episode_title>.*)$', title_string) if not title_match: # At The Movies Series 8 Episode 13 title_match = re.search( '^(?P<title>.*)\s+[Ss]eries\s?(?P<series>\w+)\s[Ee]pisode\s?(?P<episode>\d+)$', title_string) if not title_match: # Astro Boy Episode 34 Shape Shifter title_match = re.search( '^(?P<title>.*)\s[Ee]pisode\s?(?P<episode>\d+)\s(?P<episode_title>.*)$', title_string) if not title_match: #Country Town Rescue Episode 5 title_match = re.search( '^(?P<title>.*)\s[Ee]pisode\s?(?P<episode>\d+)$', title_string) if not title_match: # 7.30 10/05/12 title_match = re.search( '^(?P<title>.*)\s(?P<episode_title>\d+/\d+/\d+)$', title_string) if not title_match: # 7.30 Budget Special Report 2012 Right Of Reply Special Edition title_match = re.search( '^(?P<title>.* 2012)\s(?P<episode_title>.*)$', title_string) if not title_match: # Bananas In Pyjamas Morgan's Cafe title_match = re.search( "^(?P<title>%s)\s(?P<episode_title>.*)$" % series_title, title_string) if not title_match: # Anything else title_match = re.search("^(?P<title>.*)$", title_string) title_parts = title_match.groupdict() new_program.title = title_parts.get('title') new_program.episode_title = title_parts.get('episode_title') new_program.series = title_parts.get('series') new_program.episode = title_parts.get('episode') new_program.description = item.get('d') new_program.url = item.get('n') new_program.livestream = item.get('r') new_program.thumbnail = item.get('s') new_program.duration = item.get('j') temp_date = item.get('f') timestamp = time.mktime(time.strptime(temp_date, '%Y-%m-%d %H:%M:%S')) new_program.date = datetime.date.fromtimestamp(timestamp) programs_list.append(new_program) return programs_list