Exemple #1
0
    def create_json_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[str,any] 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(result_set)
        url = "http://playapi.mtgx.tv/v3/videos/stream/%(id)s" % result_set
        item = MediaItem(result_set["title"], url)
        item.type = "video"
        item.thumb = self.parentItem.thumb
        item.icon = self.parentItem.icon
        item.description = result_set.get("summary", None)

        aired_at = result_set.get("airedAt", None)
        if aired_at is None:
            aired_at = result_set.get("publishedAt", None)
        if aired_at is not None:
            # 2016-05-20T15:05:00+00:00
            aired_at = aired_at.split("+")[0].rstrip('Z')
            time_stamp = DateHelper.get_date_from_string(
                aired_at, "%Y-%m-%dT%H:%M:%S")
            item.set_date(*time_stamp[0:6])

        item.thumb = self.__get_thumb_image(result_set.get("image"))

        # webvttPath / samiPath
        # loginRequired
        is_premium = result_set.get("loginRequired", False)
        if is_premium and AddonSettings.hide_premium_items():
            Logger.debug("Found premium item, hiding it.")
            return None

        srt = result_set.get("samiPath")
        if not srt:
            srt = result_set.get("subtitles_webvtt")
        if srt:
            Logger.debug("Storing SRT/WebVTT path: %s", srt)
            part = item.create_new_empty_media_part()
            part.Subtitle = srt
        return item
    def create_video_item_json(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

        """

        Logger.trace(result_set)

        image_data = result_set.get("media", [])
        thumb = None
        url = None
        for image in image_data:
            thumb = image.get("imageHigh", image["image"])
            url = image.get("url")

        item = MediaItem(result_set["title"], url)
        item.type = "video"
        item.icon = self.icon
        item.thumb = thumb or self.noImage
        item.complete = True
        item.description = result_set.get("text")
        part = item.create_new_empty_media_part()
        M3u8.update_part_with_m3u8_streams(part,
                                           url,
                                           proxy=self.proxy,
                                           channel=self)

        # Let's not do the time now
        time_stamp = result_set["created"]
        date_time = DateHelper.get_date_from_posix(time_stamp)
        item.set_date(date_time.year, date_time.month, date_time.day,
                      date_time.hour, date_time.minute, date_time.second)
        return item
    def create_show_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 dict[str,Any] 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(result_set)

        start_date = result_set['start']  # 2017-01-01T00:00:00+01:00
        start_time_stamp = DateHelper.get_date_from_string(
            start_date.split("+")[0], "%Y-%m-%dT%H:%M:%S")
        end_date = result_set['end']
        end_time_stamp = DateHelper.get_date_from_string(
            end_date.split("+")[0], "%Y-%m-%dT%H:%M:%S")
        title = "%02d:%02d - %02d:%02d: %s" % (
            start_time_stamp.tm_hour, start_time_stamp.tm_min,
            end_time_stamp.tm_hour, end_time_stamp.tm_min, result_set['title'])
        item = MediaItem(title, "", type="video")
        item.description = result_set.get("description")

        item.thumb = self.noImage
        if "image" in result_set:
            if not item.description:
                item.description = result_set["image"].get("alt", None)
            item.thumb = "https://static.538.nl/%s" % (
                result_set["image"]['src'], )

        item.icon = self.icon
        item.set_date(*start_time_stamp[0:6])
        item.description = result_set.get('description')
        if "playbackUrls" in result_set and result_set["playbackUrls"]:
            title_format = "%%02d:%%02d - %s" % (result_set['title'], )
            item.complete = True
            hour = start_time_stamp.tm_hour
            for stream in result_set["playbackUrls"]:
                if stream.startswith("//"):
                    stream = "https:%s" % (stream, )
                part = item.create_new_empty_media_part()
                part.Name = title_format % (hour, start_time_stamp.tm_min)
                part.append_media_stream(stream, 0)
                hour += 1
        elif "showUrl" in result_set and result_set["showUrl"]:
            title_format = "%%02d:%%02d - %s" % (result_set['title'], )
            stream = result_set["showUrl"]
            item.complete = True
            hour = start_time_stamp.tm_hour
            if stream.startswith("//"):
                stream = "https:%s" % (stream, )
            part = item.create_new_empty_media_part()
            part.Name = title_format % (hour, start_time_stamp.tm_min)
            part.append_media_stream(stream, 0)
            hour += 1
        else:
            Logger.warning("Found item without streams: %s", item)
            return None
        return item
    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
Exemple #5
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 dict[str,Any] 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(result_set)

        title = result_set["title"]
        title = "%s - %s" % (self.parentItem.name, title)

        thumb = result_set["thumb"]
        year, month, day = result_set["posted"].split("-")
        item = MediaItem(title, self.parentItem.url)
        item.icon = self.icon
        item.description = self.parentItem.description
        item.type = 'video'
        item.thumb = thumb
        item.fanart = self.parentItem.fanart
        item.set_date(year, month, day)

        part = item.create_new_empty_media_part()
        part.HttpHeaders[
            "User-Agent"] = "QuickTime/7.6 (qtver=7.6;os=Windows NT 6.0Service Pack 2)"

        if "versions" in result_set and "enus" in result_set[
                "versions"] and "sizes" in result_set["versions"]["enus"]:
            streams = result_set["versions"]["enus"]["sizes"]
            stream_types = ("src", "srcAlt")
            bitrates = {"hd1080": 8300, "hd720": 5300, "sd": 1200}
            for s in streams:
                bitrate = bitrates.get(s, 0)
                stream_data = streams[s]

                # find all possible stream stream types
                for t in stream_types:
                    if t in stream_data:
                        stream_url = stream_data[t]
                        if stream_url.endswith(".mov"):
                            # movs need to have a 'h' before the quality
                            parts = stream_url.rsplit("_", 1)
                            if len(parts) == 2:
                                Logger.trace(parts)
                                stream_url = "%s_h%s" % (parts[0], parts[1])
                            part.append_media_stream(stream_url, bitrate)
                        else:
                            part.append_media_stream(stream_url, bitrate)
                        item.complete = True

        return item
Exemple #6
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[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

        """

        Logger.trace(result_set)

        drm_locked = False
        geo_blocked = result_set["is_geo_blocked"]

        title = result_set["title"]
        if ("_links" not in result_set or "stream" not in result_set["_links"]
                or "href" not in result_set["_links"]["stream"]):
            Logger.warning("No streams found for %s", title)
            return None

        # the description
        description = result_set["description"].strip()  # The long version
        summary = result_set["summary"].strip()  # The short version
        # Logger.Trace("Comparing:\nDesc: %s\nSumm:%s", description, summary)
        if not description.startswith(summary):
            # the descripts starts with the summary. Don't show
            description = "%s\n\n%s" % (summary, description)

        video_type = result_set["type"]
        if not video_type == "program":
            title = "%s (%s)" % (title, video_type.title())

        elif result_set["format_position"][
                "is_episodic"]:  # and resultSet["format_position"]["episode"] != "0":
            # make sure we show the episodes and seaso
            # season = int(resultSet["format_position"]["season"])
            episode = int(result_set["format_position"]["episode"] or "0")
            webisode = result_set.get("webisode", False)

            # if the name had the episode in it, translate it
            if episode > 0 and not webisode:
                description = "%s\n\n%s" % (title, description)
                title = "%s - %s %s %s %s" % (
                    result_set["format_title"], self.seasonLabel,
                    result_set["format_position"]["season"], self.episodeLabel,
                    result_set["format_position"]["episode"])
            else:
                Logger.debug(
                    "Found episode number '0' for '%s', "
                    "using name instead of episode number", title)

        url = result_set["_links"]["stream"]["href"]
        item = MediaItem(title, url)

        date_info = None
        date_format = "%Y-%m-%dT%H:%M:%S"
        if "broadcasts" in result_set and len(result_set["broadcasts"]) > 0:
            date_info = result_set["broadcasts"][0]["air_at"]
            Logger.trace("Date set from 'air_at'")

            if "playable_from" in result_set["broadcasts"][0]:
                start_date = result_set["broadcasts"][0]["playable_from"]
                playable_from = DateHelper.get_date_from_string(
                    start_date[0:-6], date_format)
                playable_from = datetime.datetime(*playable_from[0:6])
                if playable_from > datetime.datetime.now():
                    drm_locked = True

        elif "publish_at" in result_set:
            date_info = result_set["publish_at"]
            Logger.trace("Date set from 'publish_at'")

        if date_info is not None:
            # publish_at=2007-09-02T21:55:00+00:00
            info = date_info.split("T")
            date_info = info[0]
            time_info = info[1]
            date_info = date_info.split("-")
            time_info = time_info.split(":")
            item.set_date(date_info[0], date_info[1], date_info[2],
                          time_info[0], time_info[1], 0)

        item.type = "video"
        item.complete = False
        item.icon = self.icon
        item.isGeoLocked = geo_blocked
        item.isDrmProtected = drm_locked

        thumb_data = result_set['_links'].get('image', None)
        if thumb_data is not None:
            # Older version
            # item.thumbUrl = thumb_data['href'].replace("{size}", "thumb")
            item.thumb = self.__get_thumb_image(thumb_data['href'])

        item.description = description

        srt = result_set.get("sami_path")
        if not srt:
            srt = result_set.get("subtitles_webvtt")
        if srt:
            Logger.debug("Storing SRT/WebVTT path: %s", srt)
            part = item.create_new_empty_media_part()
            part.Subtitle = srt
        return item
Exemple #7
0
    def add_others(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 = []

        others = MediaItem(
            "\b.: Populair :.",
            "https://api.kijk.nl/v2/default/sections/popular_PopularVODs?offset=0"
        )
        items.append(others)

        days = MediaItem("\b.: Deze week :.", "#lastweek")
        items.append(days)

        search = MediaItem("\b.: Zoeken :.", "searchSite")
        search.complete = True
        search.icon = self.icon
        search.thumb = self.noImage
        search.dontGroup = True
        search.HttpHeaders = {"X-Requested-With": "XMLHttpRequest"}
        items.append(search)

        if self.channelCode == "veronica":
            live = LanguageHelper.get_localized_string(
                LanguageHelper.LiveStreamTitleId)
            live_radio = MediaItem("Radio Veronica {}".format(live), "")
            live_radio.type = "video"
            live_radio.icon = self.icon
            live_radio.thumb = self.noImage
            live_radio.dontGroup = True

            part = live_radio.create_new_empty_media_part()
            live_stream = "https://talparadiohls-i.akamaihd.net/hls/live/585615/VR-Veronica-1/playlist.m3u8"
            if AddonSettings.use_adaptive_stream_add_on(with_encryption=False,
                                                        channel=self):
                stream = part.append_media_stream(live_stream, 0)
                M3u8.set_input_stream_addon_input(stream, self.proxy)
                live_radio.complete = True
            else:
                for s, b in M3u8.get_streams_from_m3u8(live_stream,
                                                       self.proxy):
                    live_radio.complete = True
                    part.append_media_stream(s, b)

            items.append(live_radio)

        Logger.debug("Pre-Processing finished")
        return data, items
    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