def AddLiveChannel(self, data): Logger.Info("Performing Pre-Processing") # if self.channelCode != "vtm": # return data, [] username = AddonSettings.GetSetting("mediaan_username") if not username: return data, [] items = [] if self.channelCode == "vtm": item = MediaItem("Live VTM", "#livestream") else: item = MediaItem("Live Q2", "#livestream") item.type = "video" item.isLive = True item.fanart = self.fanart item.thumb = self.noImage now = datetime.datetime.now() item.SetDate(now.year, now.month, now.day, now.hour, now.minute, now.second) items.append(item) if self.channelCode == "vtm": recent = MediaItem("\a.: Recent :.", "https://vtm.be/video/volledige-afleveringen/id") item.fanart = self.fanart item.thumb = self.noImage item.dontGroup = True items.append(recent) Logger.Debug("Pre-Processing finished") return data, items
def add_live_channel(self, data): """ Performs pre-process actions for data processing. Accepts an data from the process_folder_list method, BEFORE the items are processed. Allows setting of parameters (like title etc) for the channel. Inside this method the <data> could be changed and additional items can be created. The return values should always be instantiated in at least ("", []). :param str data: The retrieve data that was loaded for the current item and URL. :return: A tuple of the data and a list of MediaItems that were generated. :rtype: tuple[str|JsonHelper,list[MediaItem]] """ Logger.info("Performing Pre-Processing") items = [] title = LanguageHelper.get_localized_string( LanguageHelper.LiveStreamTitleId) item = MediaItem("\a.: {} :.".format(title), "") item.type = "folder" items.append(item) live_item = MediaItem(title, "#livestream") live_item.type = "video" live_item.isLive = True item.items.append(live_item) Logger.debug("Pre-Processing finished") return data, items
def create_live_channel_item(self, result_set): """ Creates a MediaItem of type 'video' for live video using the result_set from the regex. This method creates a new MediaItem from the Regular Expression or Json results <result_set>. The method should be implemented by derived classes and are specific to the channel. If the item is completely processed an no further data needs to be fetched the self.complete property should be set to True. If not set to True, the self.update_video_item method is called if the item is focussed or selected for playback. :param list[str]|dict[str,dict|str] result_set: The result_set of the self.episodeItemRegex :return: A new MediaItem of type 'video' or 'audio' (despite the method's name). :rtype: MediaItem|None """ # noinspection PyTypeChecker url = "{}{}?apiKey={}".format(self.baseUrl, result_set["_links"]["manifest"]["href"], self.__api_key) live_data = result_set["_embedded"]["playback"] # type: dict item = MediaItem(live_data["title"], url) item.type = "video" item.isLive = True item.isGeoLocked = live_data.get("isGeoBlocked") # noinspection PyTypeChecker self.__get_image(live_data["posters"][0]["image"]["items"], "pixelWidth", "url") return item
def create_live_channel(self, result_set): """ Creates a MediaItem of type 'video' using the result_set from the regex. This method creates a new MediaItem from the Regular Expression or Json results <result_set>. The method should be implemented by derived classes and are specific to the channel. If the item is completely processed an no further data needs to be fetched the self.complete property should be set to True. If not set to True, the self.update_video_item method is called if the item is focussed or selected for playback. :param dict result_set: The result_set of the self.episodeItemRegex :return: A new MediaItem of type 'video' or 'audio' (despite the method's name). :rtype: MediaItem|None """ item_type = result_set["sys"]["contentType"]["sys"]["id"] if item_type.lower() != "station": return None Logger.trace(result_set) fields = result_set["fields"] stream_types = fields["streamType"] # We need to do some fuzzy looking-up thumb_id = fields["backgroundGallery"][0]["sys"]["id"] if "file" not in self.__liveData[thumb_id]["fields"]: thumb_id = self.__liveData[thumb_id]["fields"]["media"]["sys"][ "id"] thumb = self.__liveData[thumb_id]["fields"]["file"]["url"] if thumb.startswith("//"): thumb = "https:{0}".format(thumb) items = [] for stream_type in stream_types: if stream_type == "video": stream_id = fields["videoStream"]["sys"]["id"] stream_fields = self.__liveData[stream_id]["fields"] url = stream_fields["source"] title = stream_fields["title"] else: stream_id = fields["tritonStream"]["sys"]["id"] stream_fields = self.__liveData[stream_id]["fields"] stream_id = stream_fields["mountPoint"] title = stream_fields["title"] rnd = int(time.time()) url = "https://playerservices.streamtheworld.com/api/livestream?station={0}&" \ "transports=http%2Chls%2Chlsts&version=1.9&request.preventCache={1}"\ .format(stream_id, rnd) item = MediaItem(title, url) item.type = 'video' item.isLive = True item.thumb = thumb item.metaData["streamType"] = stream_type items.append(item) return items
def create_live_item(self, result_set): """ Creates a live MediaItem of type 'video' using the result_set from the regex. This method creates a new MediaItem from the Regular Expression or Json results <result_set>. The method should be implemented by derived classes and are specific to the channel. If the item is completely processed an no further data needs to be fetched the self.complete property should be set to True. If not set to True, the self.update_video_item method is called if the item is focussed or selected for playback. :param dict[str,str|dict[str,str]] result_set: The result_set of the self.episodeItemRegex :return: A new MediaItem of type 'video' or 'audio' (despite the method's name). :rtype: MediaItem|None """ url = result_set["stream"]["highQualityUrl"] title = result_set["title"] or result_set["id"].title() item = MediaItem(title, url) item.type = "video" item.isLive = True if item.url.endswith(".mp3"): item.append_single_stream(item.url) item.complete = True return item return item
def create_channel_item(self, channel): """ Creates a MediaItem of type 'video' for a live channel using the result_set from the regex. This method creates a new MediaItem from the Regular Expression or Json results <result_set>. The method should be implemented by derived classes and are specific to the channel. If the item is completely processed an no further data needs to be fetched the self.complete property should be set to True. If not set to True, the self.update_video_item method is called if the item is focussed or selected for playback. :param list[str]|dict channel: The result_set of the self.episodeItemRegex :return: A new MediaItem of type 'video' or 'audio' (despite the method's name). :rtype: MediaItem|None """ Logger.trace(channel) title = channel["programmeTitle"] episode = channel.get("episodeTitle", None) thumb = self.noImage channel_title = channel["channelName"] description = channel.get("description") channel_id = channel["channel"].lower() if channel_id == "svtbarn": channel_id = "barnkanalen" date_format = "%Y-%m-%dT%H:%M:%S" start_time = DateHelper.get_date_from_string( channel["publishingTime"][:19], date_format) end_time = DateHelper.get_date_from_string( channel["publishingEndTime"][:19], date_format) if episode: title = "%s: %s - %s (%02d:%02d - %02d:%02d)" \ % (channel_title, title, episode, start_time.tm_hour, start_time.tm_min, end_time.tm_hour, end_time.tm_min) else: title = "%s: %s (%02d:%02d - %02d:%02d)" \ % (channel_title, title, start_time.tm_hour, start_time.tm_min, end_time.tm_hour, end_time.tm_min) channel_item = MediaItem( title, "https://www.svt.se/videoplayer-api/video/ch-%s" % (channel_id.lower(), )) channel_item.type = "video" channel_item.description = description channel_item.isLive = True channel_item.isGeoLocked = True channel_item.thumb = thumb if "titlePageThumbnailIds" in channel and channel[ "titlePageThumbnailIds"]: channel_item.thumb = "https://www.svtstatic.se/image/wide/650/%s.jpg" % ( channel["titlePageThumbnailIds"][0], ) return channel_item
def add_missing_live_streams(self, data): """ Performs pre-process actions for data processing. Accepts an data from the process_folder_list method, BEFORE the items are processed. Allows setting of parameters (like title etc) for the channel. Inside this method the <data> could be changed and additional items can be created. The return values should always be instantiated in at least ("", []). :param str data: The retrieve data that was loaded for the current item and URL. :return: A tuple of the data and a list of MediaItems that were generated. :rtype: tuple[str|JsonHelper,list[MediaItem]] """ items = [] slam = MediaItem( "Slam! TV", "https://hls.slam.nl/streaming/hls/SLAM!/playlist.m3u8") slam.icon = self.icon slam.thumb = self.noImage slam.type = "video" slam.isLive = True items.append(slam) slam_fm = MediaItem( "Slam! FM", "https://18973.live.streamtheworld.com/SLAM_AAC.aac" "?ttag=PLAYER%3ANOPREROLL&tdsdk=js-2.9" "&pname=TDSdk&pversion=2.9&banners=none") slam_fm.icon = self.icon slam_fm.thumb = self.noImage slam_fm.type = "audio" slam_fm.isLive = True slam_fm.append_single_stream(slam_fm.url) slam_fm.complete = True items.append(slam_fm) data = JsonHelper(data) for e in data.get_value("includes", "Entry"): self.__liveData[e["sys"]["id"]] = e for e in data.get_value("includes", "Asset"): self.__liveData[e["sys"]["id"]] = e return data, items
def StievieChannelMenu(self, data): items = [] live = MediaItem("Live %s" % (self.parentItem.name, ), "#livestream") live.isLive = True live.type = "video" live.description = self.parentItem.description live.metaData = self.parentItem.metaData live.thumb = self.parentItem.thumb items.append(live) if not self.__dashStreamsSupported: # Only list the channel content if DASH is supported return data, items # https://epg.medialaan.io/epg/v2/schedule?date=2017-04-25&channels%5B%5D=vtm&channels%5B%5D=2be&channels%5B%5D=vitaya&channels%5B%5D=caz&channels%5B%5D=kzoom&channels%5B%5D=kadet&channels%5B%5D=qmusic # https://epg.medialaan.io/epg/v2/schedule?date=2017-04-25&channels[]=vtm&channels[]=2be&channels[]=vitaya&channels[]=caz&channels[]=kzoom&channels[]=kadet&channels[]=qmusic # https://epg.medialaan.io/epg/v2/schedule?date=2017-05-04&channels[]=vtm&channels[]=2be&channels[]=vitaya&channels[]=caz&channels[]=kzoom&channels[]=kadet&channels[]=qmusic channelId = self.parentItem.metaData["channelId"] channels = (channelId, ) query = "&channels%%5B%%5D=%s" % ("&channels%5B%5D=".join(channels), ) today = datetime.datetime.now() days = [ "Maandag", "Dinsdag", "Woensdag", "Donderdag", "Vrijdag", "Zaterdag", "Zondag" ] for i in range(0, 7, 1): airDate = today - datetime.timedelta(i) Logger.Trace("Adding item for: %s", airDate) day = days[airDate.weekday()] if i == 0: day = "Vandaag" elif i == 1: day = "Gisteren" elif i == 2: day = "Eergisteren" title = "%04d-%02d-%02d - %s" % (airDate.year, airDate.month, airDate.day, day) url = "https://epg.medialaan.io/epg/v2/schedule?date=%d-%02d-%02d%s" % ( airDate.year, airDate.month, airDate.day, query) extra = MediaItem(title, url) extra.complete = True extra.icon = self.icon extra.thumb = self.noImage extra.dontGroup = True extra.SetDate(airDate.year, airDate.month, airDate.day, text="") extra.metaData["airDate"] = airDate items.append(extra) return data, items
def add_live_streams_and_recent(self, data): """ Adds the live streams for RTL-Z. Accepts an data from the process_folder_list method, BEFORE the items are processed. Allows setting of parameters (like title etc) for the channel. Inside this method the <data> could be changed and additional items can be created. The return values should always be instantiated in at least ("", []). :param str data: The retrieve data that was loaded for the current item and URL. :return: A tuple of the data and a list of MediaItems that were generated. :rtype: tuple[str|JsonHelper,list[MediaItem]] """ items = [] # let's add the RTL-Z live stream rtlz_live = MediaItem("RTL Z Live Stream", "") rtlz_live.icon = self.icon rtlz_live.thumb = self.noImage rtlz_live.complete = True rtlz_live.isLive = True rtlz_live.dontGroup = True stream_item = MediaItem( "RTL Z: Live Stream", "http://www.rtl.nl/(config=RTLXLV2,channel=rtlxl,progid=rtlz,zone=inlineplayer.rtl.nl/rtlz,ord=0)/system/video/wvx/components/financien/rtlz/miMedia/livestream/rtlz_livestream.xml/1500.wvx" ) stream_item.icon = self.icon stream_item.thumb = self.noImage stream_item.complete = True stream_item.type = "video" stream_item.dontGroup = True stream_item.append_single_stream("http://mss6.rtl7.nl/rtlzbroad", 1200) stream_item.append_single_stream("http://mss26.rtl7.nl/rtlzbroad", 1200) stream_item.append_single_stream("http://mss4.rtl7.nl/rtlzbroad", 1200) stream_item.append_single_stream("http://mss5.rtl7.nl/rtlzbroad", 1200) stream_item.append_single_stream("http://mss3.rtl7.nl/rtlzbroad", 1200) rtlz_live.items.append(stream_item) items.append(rtlz_live) # Add recent items data, recent_items = self.add_recent_items(data) return data, recent_items
def add_categories(self, data): """ Adds categories to the main listings. The return values should always be instantiated in at least ("", []). :param str data: The retrieve data that was loaded for the current item and URL. :return: A tuple of the data and a list of MediaItems that were generated. :rtype: tuple[str|JsonHelper,list[MediaItem]] """ Logger.info("Performing Pre-Processing") items = [] if self.parentItem and "code" in self.parentItem.metaData: self.__currentChannel = self.parentItem.metaData["code"] Logger.info("Only showing items for channel: '%s'", self.__currentChannel) return data, items cat = MediaItem("\a.: Categoriën :.", "https://www.vrt.be/vrtnu/categorieen/") cat.fanart = self.fanart cat.thumb = self.noImage cat.icon = self.icon cat.dontGroup = True items.append(cat) live = MediaItem("\a.: Live Streams :.", "https://services.vrt.be/videoplayer/r/live.json") live.fanart = self.fanart live.thumb = self.noImage live.icon = self.icon live.dontGroup = True live.isLive = True items.append(live) channel_text = LanguageHelper.get_localized_string(30010) channels = MediaItem("\a.: %s :." % (channel_text, ), "#channels") channels.fanart = self.fanart channels.thumb = self.noImage channels.icon = self.icon channels.dontGroup = True items.append(channels) Logger.debug("Pre-Processing finished") return data, items
def create_live_stream(self, result_set): """ Creates a MediaItem of type 'video' for a live stream using the result_set from the regex. This method creates a new MediaItem from the Regular Expression or Json results <result_set>. The method should be implemented by derived classes and are specific to the channel. If the item is completely processed an no further data needs to be fetched the self.complete property should be set to True. If not set to True, the self.update_video_item method is called if the item is focussed or selected for playback. :param list[str]|dict result_set: The result_set of the self.episodeItemRegex :return: A new MediaItem of type 'video' or 'audio' (despite the method's name). :rtype: MediaItem|None """ items = [] for key_value, stream_value in result_set.items(): Logger.trace(stream_value) # noinspection PyArgumentList channel_data = self.__channelData.get(key_value, None) if not channel_data: continue url = channel_data[ "url"] if "url" in channel_data else stream_value["mpd"] live_item = MediaItem(channel_data["title"], url) live_item.isLive = True live_item.type = 'video' live_item.fanart = channel_data.get("fanart", self.fanart) live_item.thumb = channel_data.get("icon", self.icon) live_item.icon = channel_data.get("icon", self.icon) live_item.metaData["channel_key"] = key_value items.append(live_item) return items
def add_category_and_live_items(self, data): """ Performs pre-process actions for data processing. Accepts an data from the process_folder_list method, BEFORE the items are processed. Allows setting of parameters (like title etc) for the channel. Inside this method the <data> could be changed and additional items can be created. The return values should always be instantiated in at least ("", []). :param str data: The retrieve data that was loaded for the current item and URL. :return: A tuple of the data and a list of MediaItems that were generated. :rtype: tuple[str|JsonHelper,list[MediaItem]] """ Logger.info("Performing Pre-Processing") items = [] sub_items = { "\a.: Direct :.": "%s/auvio/direct/" % (self.baseUrl, ), "\a.: Catégories :.": "http://www.rtbf.be/news/api/menu?site=media" } for k, v in sub_items.items(): item = MediaItem(k, v) item.complete = True item.dontGroup = True items.append(item) item.isLive = v.endswith('/direct/') Logger.debug("Pre-Processing finished") return data, items
def add_live_channels_and_folders(self, data): """ Performs pre-process actions for data processing. Accepts an data from the process_folder_list method, BEFORE the items are processed. Allows setting of parameters (like title etc) for the channel. Inside this method the <data> could be changed and additional items can be created. The return values should always be instantiated in at least ("", []). :param str data: The retrieve data that was loaded for the current item and URL. :return: A tuple of the data and a list of MediaItems that were generated. :rtype: tuple[str|JsonHelper,list[MediaItem]] """ Logger.info("Generating Live channels") items = [] live_channels = [ { "name": "BBC 1 HD", "code": "bbc_one_hd", "image": "bbc1large.png" }, { "name": "BBC 2 HD", "code": "bbc_two_hd", "image": "bbc2large.png" }, { "name": "BBC 3 HD", "code": "bbc_three_hd", "image": "bbc3large.png" }, { "name": "BBC 4 HD", "code": "bbc_four_hd", "image": "bbc4large.png" }, { "name": "CBBC", "code": "cbbc_hd", "image": "cbbclarge.png" }, { "name": "CBeebies", "code": "cbeebies_hd", "image": "cbeebieslarge.png" }, { "name": "BBC News Channel", "code": "bbc_news24", "image": "bbcnewslarge.png" }, { "name": "BBC Parliament", "code": "bbc_parliament", "image": "bbcparliamentlarge.png" }, { "name": "Alba", "code": "bbc_alba", "image": "bbcalbalarge.png" }, { "name": "S4C", "code": "s4cpbs", "image": "bbchdlarge.png" }, { "name": "BBC One London", "code": "bbc_one_london", "image": "bbchdlarge.png" }, { "name": "BBC One Scotland", "code": "bbc_one_scotland_hd", "image": "bbchdlarge.png" }, { "name": "BBC One Northern Ireland", "code": "bbc_one_northern_ireland_hd", "image": "bbchdlarge.png" }, { "name": "BBC One Wales", "code": "bbc_one_wales_hd", "image": "bbchdlarge.png" }, { "name": "BBC Two Scotland", "code": "bbc_two_scotland", "image": "bbchdlarge.png" }, { "name": "BBC Two Northern Ireland", "code": "bbc_two_northern_ireland_digital", "image": "bbchdlarge.png" }, { "name": "BBC Two Wales", "code": "bbc_two_wales_digital", "image": "bbchdlarge.png" }, ] live = MediaItem("Live Channels", "") live.dontGroup = True live.type = "folder" items.append(live) for channel in live_channels: url = "http://a.files.bbci.co.uk/media/live/manifesto/audio_video/simulcast/hds/uk/pc/ak/%(code)s.f4m" % channel item = MediaItem(channel["name"], url) item.isGeoLocked = True item.isLive = True item.type = "video" item.complete = False item.thumb = self.get_image_location(channel["image"]) live.items.append(item) extra = MediaItem("Shows (A-Z)", "#alphalisting") extra.complete = True extra.icon = self.icon extra.thumb = self.noImage extra.description = "Alphabetical show listing of BBC shows" extra.dontGroup = True extra.set_date(2200, 1, 1, text="") items.append(extra) return data, items
def process_live_items(self, data): # NOSONAR """ Performs pre-process actions that either return multiple live channels that are present in the live url or an actual list item if a single live stream is present. Accepts an data from the process_folder_list method, BEFORE the items are processed. Allows setting of parameters (like title etc) for the channel. Inside this method the <data> could be changed and additional items can be created. The return values should always be instantiated in at least ("", []). :param str data: The retrieve data that was loaded for the current item and URL. :return: A tuple of the data and a list of MediaItems that were generated. :rtype: tuple[str|JsonHelper,list[MediaItem]] """ items = [] Logger.info("Adding Live Streams") if self.liveUrl.endswith(".m3u8"): # We actually have a single stream. title = "{} - {}".format( self.channelName, LanguageHelper.get_localized_string( LanguageHelper.LiveStreamTitleId)) live_item = MediaItem(title, self.liveUrl) live_item.type = 'video' live_item.icon = self.icon live_item.thumb = self.noImage live_item.isLive = True if self.channelCode == "rtvdrenthe": # RTV Drenthe actually has a buggy M3u8 without master index. live_item.append_single_stream(live_item.url, 0) live_item.complete = True items.append(live_item) return "", items # we basically will check for live channels json_data = JsonHelper(data, logger=Logger.instance()) live_streams = json_data.get_value() Logger.trace(live_streams) if "videos" in live_streams: Logger.debug("Multiple streams found") live_streams = live_streams["videos"] elif not isinstance(live_streams, (list, tuple)): Logger.debug("Single streams found") live_streams = (live_streams, ) else: Logger.debug("List of stream found") live_stream_value = None for streams in live_streams: Logger.debug("Adding live stream") title = streams.get( 'name') or "%s - Live TV" % (self.channelName, ) live_item = MediaItem(title, self.liveUrl) live_item.type = 'video' live_item.complete = True live_item.icon = self.icon live_item.thumb = self.noImage live_item.isLive = True part = live_item.create_new_empty_media_part() for stream in streams: Logger.trace(stream) bitrate = None # used in Omrop Fryslan if stream == "android" or stream == "iPhone": bitrate = 250 url = streams[stream]["videoLink"] elif stream == "iPad": bitrate = 1000 url = streams[stream]["videoLink"] # used in RTV Utrecht elif stream == "androidLink" or stream == "iphoneLink": bitrate = 250 url = streams[stream] elif stream == "ipadLink": bitrate = 1000 url = streams[stream] elif stream == "tabletLink": bitrate = 300 url = streams[stream] # These windows stream won't work # elif stream == "windowsLink": # bitrate = 1200 # url = streams[stream] # elif stream == "wpLink": # bitrate = 1200 # url = streams[stream] elif stream == "name": Logger.trace("Ignoring stream '%s'", stream) else: Logger.warning("No url found for type '%s'", stream) # noinspection PyUnboundLocalVariable if "livestreams.omroep.nl/live/" in url and url.endswith( "m3u8"): Logger.info("Found NPO Stream, adding ?protection=url") url = "%s?protection=url" % (url, ) if bitrate: part.append_media_stream(url, bitrate) if url == live_stream_value and ".m3u8" in url: # if it was equal to the previous one, assume we have a m3u8. Reset the others. Logger.info( "Found same M3u8 stream for all streams for this Live channel, using that one: %s", url) live_item.MediaItemParts = [] live_item.url = url live_item.complete = False break elif "playlist.m3u8" in url: # if we have a playlist, use that one. Reset the others. Logger.info( "Found M3u8 playlist for this Live channel, using that one: %s", url) live_item.MediaItemParts = [] live_item.url = url live_item.complete = False break else: # add it to the possibilities live_stream_value = url items.append(live_item) return "", items
def load_programs(self, data): """ Performs pre-process actions for data processing. Accepts an data from the process_folder_list method, BEFORE the items are processed. Allows setting of parameters (like title etc) for the channel. Inside this method the <data> could be changed and additional items can be created. The return values should always be instantiated in at least ("", []). :param str data: The retrieve data that was loaded for the current item and URL. :return: A tuple of the data and a list of MediaItems that were generated. :rtype: tuple[str|JsonHelper,list[MediaItem]] """ items = [] # fetch al pages p = 1 url_format = "https://{0}/content/shows?" \ "include=images" \ "&page%5Bsize%5D=100&page%5Bnumber%5D={{0}}".format(self.baseUrlApi) # "include=images%2CprimaryChannel" \ url = url_format.format(p) data = UriHandler.open(url, proxy=self.proxy) json = JsonHelper(data) pages = json.get_value("meta", "totalPages") programs = json.get_value("data") or [] # extract the images self.__update_image_lookup(json) for p in range(2, pages + 1, 1): url = url_format.format(p) Logger.debug("Loading: %s", url) data = UriHandler.open(url, proxy=self.proxy) json = JsonHelper(data) programs += json.get_value("data") or [] # extract the images self.__update_image_lookup(json) Logger.debug("Found a total of %s items over %s pages", len(programs), pages) for p in programs: item = self.create_program_item(p) if item is not None: items.append(item) if self.recentUrl: recent_text = LanguageHelper.get_localized_string( LanguageHelper.Recent) recent = MediaItem("\b.: {} :.".format(recent_text), self.recentUrl) recent.dontGroup = True recent.fanart = self.fanart items.append(recent) # live items if self.liveUrl: live = MediaItem("\b.: Live :.", self.liveUrl) live.type = "video" live.dontGroup = True live.isGeoLocked = True live.isLive = True live.fanart = self.fanart items.append(live) search = MediaItem("\a.: Sök :.", "searchSite") search.type = "folder" search.dontGroup = True search.fanart = self.fanart items.append(search) return data, items
def add_categories_and_specials(self, data): """ Performs pre-process actions for data processing. Accepts an data from the process_folder_list method, BEFORE the items are processed. Allows setting of parameters (like title etc) for the channel. Inside this method the <data> could be changed and additional items can be created. The return values should always be instantiated in at least ("", []). :param str data: The retrieve data that was loaded for the current item and URL. :return: A tuple of the data and a list of MediaItems that were generated. :rtype: tuple[str|JsonHelper,list[MediaItem]] """ Logger.info("Performing Pre-Processing") items = [] extras = { LanguageHelper.get_localized_string(LanguageHelper.Search): ("searchSite", None, False), LanguageHelper.get_localized_string(LanguageHelper.TvShows): ("http://webapi.tv4play.se/play/programs?is_active=true&platform=tablet" "&per_page=1000&fl=nid,name,program_image,is_premium,updated_at,channel&start=0", None, False) } # Channel 4 specific items if self.channelCode == "tv4se": extras.update({ LanguageHelper.get_localized_string(LanguageHelper.Categories): ("http://webapi.tv4play.se/play/categories.json", None, False), LanguageHelper.get_localized_string(LanguageHelper.MostViewedEpisodes): ("http://webapi.tv4play.se/play/video_assets/most_viewed?type=episode" "&platform=tablet&is_live=false&per_page=%s&start=0" % (self.maxPageSize, ), None, False), }) # if self.loggedOn: # extras.update({ # "\a.: Favoriter :.": ( # "http://www.tv4play.se/program/favourites", # None, True # ), # }) today = datetime.datetime.now() days = [ LanguageHelper.get_localized_string(LanguageHelper.Monday), LanguageHelper.get_localized_string(LanguageHelper.Tuesday), LanguageHelper.get_localized_string(LanguageHelper.Wednesday), LanguageHelper.get_localized_string(LanguageHelper.Thursday), LanguageHelper.get_localized_string(LanguageHelper.Friday), LanguageHelper.get_localized_string(LanguageHelper.Saturday), LanguageHelper.get_localized_string(LanguageHelper.Sunday) ] for i in range(0, 7, 1): start_date = today - datetime.timedelta(i) end_date = start_date + datetime.timedelta(1) day = days[start_date.weekday()] if i == 0: day = LanguageHelper.get_localized_string( LanguageHelper.Today) elif i == 1: day = LanguageHelper.get_localized_string( LanguageHelper.Yesterday) Logger.trace("Adding item for: %s - %s", start_date, end_date) # Old URL: # url = "http://webapi.tv4play.se/play/video_assets?exclude_node_nids=" \ # "nyheterna,v%C3%A4der,ekonomi,lotto,sporten,nyheterna-blekinge,nyheterna-bor%C3%A5s," \ # "nyheterna-dalarna,nyheterna-g%C3%A4vle,nyheterna-g%C3%B6teborg,nyheterna-halland," \ # "nyheterna-helsingborg,nyheterna-j%C3%B6nk%C3%B6ping,nyheterna-kalmar,nyheterna-link%C3%B6ping," \ # "nyheterna-lule%C3%A5,nyheterna-malm%C3%B6,nyheterna-norrk%C3%B6ping,nyheterna-skaraborg," \ # "nyheterna-skellefte%C3%A5,nyheterna-stockholm,nyheterna-sundsvall,nyheterna-ume%C3%A5," \ # "nyheterna-uppsala,nyheterna-v%C3%A4rmland,nyheterna-v%C3%A4st,nyheterna-v%C3%A4ster%C3%A5s," \ # "nyheterna-v%C3%A4xj%C3%B6,nyheterna-%C3%B6rebro,nyheterna-%C3%B6stersund,tv4-tolken," \ # "fotbollskanalen-europa" \ # "&platform=tablet&per_page=32&is_live=false&product_groups=2&type=episode&per_page=100" url = "http://webapi.tv4play.se/play/video_assets?exclude_node_nids=" \ "&platform=tablet&per_page=32&is_live=false&product_groups=2&type=episode&per_page=100" url = "%s&broadcast_from=%s&broadcast_to=%s&" % ( url, start_date.strftime("%Y%m%d"), end_date.strftime("%Y%m%d")) extras[day] = (url, start_date, False) extras[LanguageHelper.get_localized_string( LanguageHelper.CurrentlyPlayingEpisodes )] = ( "http://webapi.tv4play.se/play/video_assets?exclude_node_nids=&platform=tablet&" "per_page=32&is_live=true&product_groups=2&type=episode&per_page=100", None, False) for name in extras: title = name url, date, is_live = extras[name] item = MediaItem(title, url) item.dontGroup = True item.complete = True item.thumb = self.noImage item.HttpHeaders = self.httpHeaders item.isLive = is_live if date is not None: item.set_date(date.year, date.month, date.day, 0, 0, 0, text=date.strftime("%Y-%m-%d")) else: item.set_date(1901, 1, 1, 0, 0, 0, text="") items.append(item) if not self.channelCode == "tv4se": return data, items # Add Live TV # live = MediaItem("\a.: Live-TV :.", # "http://tv4events1-lh.akamaihd.net/i/EXTRAEVENT5_1@324055/master.m3u8", # type="video") # live.dontGroup = True # # live.isDrmProtected = True # live.isGeoLocked = True # live.isLive = True # items.append(live) Logger.debug("Pre-Processing finished") return data, items
def create_video_item(self, result_set): """ Creates a MediaItem of type 'video' using the result_set from the regex. This method creates a new MediaItem from the Regular Expression or Json results <result_set>. The method should be implemented by derived classes and are specific to the channel. If the item is completely processed an no further data needs to be fetched the self.complete property should be set to True. If not set to True, the self.update_video_item method is called if the item is focussed or selected for playback. :param list[str]|dict result_set: The result_set of the self.episodeItemRegex :return: A new MediaItem of type 'video' or 'audio' (despite the method's name). :rtype: MediaItem|None """ Logger.trace('starting FormatVideoItem for %s', self.channelName) # Logger.Trace(result_set) # the vmanProgramId (like 1019976) leads to http://anytime.tv4.se/webtv/metafileFlash.smil?p=1019976&bw=1000&emulate=true&sl=true program_id = result_set["id"] # Logger.Debug("ProgId = %s", programId) url = "https://playback-api.b17g.net/media/%s?service=tv4&device=browser&protocol=hls" % ( program_id, ) name = result_set["title"] item = MediaItem(name, url) item.description = result_set["description"] if item.description is None: item.description = item.name # premium_expire_date_time=2099-12-31T00:00:00+01:00 date = result_set["broadcast_date_time"] (date_part, time_part) = date.split("T") (year, month, day) = date_part.split("-") (hour, minutes, rest1, zone) = time_part.split(":") item.set_date(year, month, day, hour, minutes, 00) broadcast_date = datetime.datetime(int(year), int(month), int(day), int(hour), int(minutes)) thumb_url = result_set.get("image", result_set.get("program_image")) # some images need to come via a proxy: if thumb_url and "://img.b17g.net/" in thumb_url: item.thumb = "https://imageproxy.b17g.services/?format=jpg&shape=cut" \ "&quality=90&resize=520x293&source={}"\ .format(HtmlEntityHelper.url_encode(thumb_url)) else: item.thumb = thumb_url availability = result_set["availability"] # noinspection PyTypeChecker free_period = availability["availability_group_free"] # noinspection PyTypeChecker premium_period = availability["availability_group_premium"] now = datetime.datetime.now() if False and not premium_period == "0": # always premium free_expired = now - datetime.timedelta(days=99 * 365) elif free_period == "30+" or free_period is None: free_expired = broadcast_date + datetime.timedelta(days=99 * 365) else: free_expired = broadcast_date + datetime.timedelta( days=int(free_period)) Logger.trace( "Premium info for: %s\nPremium state: %s\nFree State: %s\nBroadcast %s vs Expired %s", name, premium_period, free_period, broadcast_date, free_expired) if now > free_expired: item.isPaid = True item.type = "video" item.complete = False item.icon = self.icon item.isGeoLocked = result_set["is_geo_restricted"] item.isDrmProtected = result_set["is_drm_protected"] item.isLive = result_set.get("is_live", False) if item.isLive: item.url = "{0}&is_live=true".format(item.url) return item
def add_live_stream(self, data): """ Performs pre-process actions for data processing. Accepts an data from the process_folder_list method, BEFORE the items are processed. Allows setting of parameters (like title etc) for the channel. Inside this method the <data> could be changed and additional items can be created. The return values should always be instantiated in at least ("", []). :param str data: The retrieve data that was loaded for the current item and URL. :return: A tuple of the data and a list of MediaItems that were generated. :rtype: tuple[str|JsonHelper,list[MediaItem]] """ items = [] item = MediaItem("\a.: TWiT.TV Live :.", "http://live.twit.tv/") item.thumb = self.noImage item.icon = self.icon item.complete = True playback_item = MediaItem("Play Live", "http://live.twit.tv/") playback_item.type = "playlist" playback_item.thumb = self.noImage playback_item.icon = self.icon playback_item.isLive = True playback_part = playback_item.create_new_empty_media_part() # noinspection PyStatementEffect """ BitGravity There are two streams available from BitGravity; a 512 kbps low-bandwidth stream and a 1 Mbps high-bandwidth stream. UStream This is the default stream. The UStream stream is a variable stream that maxes at 2.2 Mbps and adjusts down based on your bandwidth. Justin.tv The Justin.tv stream is a 2.2 mbps high-bandwidth stream that will adjust to lower bandwidth and resolutions. Flosoft.biz The Flosoft.biz stream is a 5 resolution/bitrate HLS stream, intended for our app developers. Please see Flosoft Developer Section. This stream is hosted by TWiT through Flosoft.biz """ # http://wiki.twit.tv/wiki/TWiT_Live#Direct_links_to_TWiT_Live_Video_Streams media_urls = { # Justin TV # "2000": "http://usher.justin.tv/stream/multi_playlist/twit.m3u8", # Flosoft (http://wiki.twit.tv/wiki/Developer_Guide#Flosoft.biz) "264": "http://hls.cdn.flosoft.biz/flosoft/mp4:twitStream_240/playlist.m3u8", "512": "http://hls.cdn.flosoft.biz/flosoft/mp4:twitStream_360/playlist.m3u8", "1024": "http://hls.cdn.flosoft.biz/flosoft/mp4:twitStream_480/playlist.m3u8", "1475": "http://hls.cdn.flosoft.biz/flosoft/mp4:twitStream_540/playlist.m3u8", "1778": "http://hls.cdn.flosoft.biz/flosoft/mp4:twitStream_720/playlist.m3u8", # UStream "1524": "http://iphone-streaming.ustream.tv/ustreamVideo/1524/streams/live/playlist.m3u8", # BitGravity # "512": "http://209.131.99.99/twit/live/low", # "1024": "http://209.131.99.99/twit/live/high", #"512": "http://64.185.191.180/cdn-live-s1/_definst_/twit/live/low/playlist.m3u8", #"1024": "http://64.185.191.180/cdn-live-s1/_definst_/twit/live/high/playlist.m3u8", } for bitrate in media_urls: playback_part.append_media_stream(media_urls[bitrate], bitrate) Logger.debug("Streams: %s", playback_part) playback_item.complete = True item.items.append(playback_item) Logger.debug("Appended: %s", playback_item) items.append(item) return data, items