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
Beispiel #5
0
    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&euml;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&eacute;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&ouml;k :.", "searchSite")
        search.type = "folder"
        search.dontGroup = True
        search.fanart = self.fanart
        items.append(search)

        return data, items
Beispiel #16
0
    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
Beispiel #17
0
    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