def create_api_episode_type(self, result_set):
        """ Creates a new MediaItem for an episode.

        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.

        :param dict result_set: The result_set of the self.episodeItemRegex

        :return: A new MediaItem of type 'folder'.
        :rtype: MediaItem|None

        """

        # This URL gives the URL that contains the show info with Season ID's
        url = "https://graph.kijk.nl/graphql-video"

        if not result_set.get("sources"):
            return None

        title = result_set["title"]
        season_number = result_set.get("seasonNumber")
        episode_number = result_set.get("tvSeasonEpisodeNumber")

        title_format = self.parentItem.metaData.get("title_format",
                                                    "s{0:02d}e{1:02d} - {2}")
        if title is None:
            serie_title = result_set["series"]["title"]
            title = title_format.format(season_number, episode_number,
                                        serie_title)
        elif season_number is not None and episode_number is not None:
            title = title_format.format(season_number, episode_number, title)

        item = MediaItem(title, url, type="video")
        item.description = result_set.get("longDescription",
                                          result_set.get("description"))
        item.set_info_label("duration",
                            int(result_set.get("duration", 0) or 0))
        item.set_info_label("genre", result_set.get("displayGenre"))
        self.__get_artwork(item, result_set.get("imageMedia"), mode="thumb")

        updated = result_set["lastPubDate"] / 1000
        date_time = DateHelper.get_date_from_posix(updated)
        item.set_date(date_time.year, date_time.month, date_time.day,
                      date_time.hour, date_time.minute, date_time.second)

        # Find the media streams
        item.metaData["sources"] = result_set["sources"]
        item.metaData["subtitles"] = result_set.get("tracks", [])

        # DRM only
        no_drm_items = [src for src in result_set["sources"] if not src["drm"]]
        item.isDrmProtected = len(no_drm_items) == 0
        return item
예제 #2
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)

        # We can either use M3u8 or Dash
        # url = "https://playback-api.b17g.net/media/%s?service=tv4&device=browser&protocol=hls" % (program_id,)
        url = "https://playback-api.b17g.net/media/%s?service=tv4&device=browser&protocol=dash" % (
            program_id, )
        name = result_set["title"]
        season = result_set.get("season", 0)
        episode = result_set.get("episode", 0)
        is_episodic = 0 < season < 1900 and not episode == 0
        if is_episodic:
            episode_text = None
            if " del " in name:
                name, episode_text = name.split(" del ", 1)
                episode_text = episode_text.lstrip("0123456789")

            if episode_text:
                episode_text = episode_text.lstrip(" -")
                name = "{} - s{:02d}e{:02d} - {}".format(
                    name, season, episode, episode_text)
            else:
                name = "{} - s{:02d}e{:02d}".format(name, season, episode)

        item = MediaItem(name, url)
        item.description = result_set["description"]
        if item.description is None:
            item.description = item.name

        if is_episodic:
            item.set_season_info(season, episode)

        # premium_expire_date_time=2099-12-31T00:00:00+01:00
        expire_date = result_set.get("expire_date_time")
        if bool(expire_date):
            self.__set_expire_time(expire_date, item)

        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))

        item.fanart = result_set.get("program_image", self.parentItem.fanart)
        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.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.name = "{}:{} - {}".format(hour, minutes, name)
            item.url = "{0}&is_live=true".format(item.url)
        if item.isDrmProtected:
            item.url = "{}&drm=widevine&is_drm=true".format(item.url)

        item.set_info_label("duration", int(result_set.get("duration", 0)))
        return item
    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 = result_set["format_position"].get("season", 0)
            episode = int(result_set["format_position"]["episode"] or "0")

            # Was it a webisode?
            # webisode = result_set.get("webisode", False)

            # if the name had the episode in it, translate it
            if episode > 0 and season > 0:  # and not webisode:
                description = "%s\n\n%s" % (title, description)
                title = "{0} - s{1:02d}e{2:02d}".format(
                    result_set["format_title"], season, episode)
            else:
                Logger.debug(
                    "Found episode '0' or websido '%s': using name instead of episode number",
                    title)

        mpx_guid = result_set.get('mpx_guid')
        if mpx_guid is None:
            url = result_set["_links"]["stream"]["href"]
        else:
            # we can use mpx_guid and https://viafree.mtg-api.com/stream-links/viafree/web/se/clear-media-guids/{}/streams
            url = "https://viafree.mtg-api.com/stream-links/viafree/web/{}/clear-media-guids/{}/streams".format(
                self.language, mpx_guid)
        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.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
        # unpublish_at=2099-12-31T00:00:00+01:00
        expire_date = result_set["unpublish_at"]
        if bool(expire_date):
            self.__set_expire_time(expire_date, item)

        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

        item.set_info_label("duration", int(result_set.get("duration", 0)))
        return item
    def create_api_video_asset_type(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)

        program_id = result_set["id"]
        url = "https://playback-api.b17g.net/media/{}?service=tv4&device=browser&protocol=dash".\
            format(program_id)

        name = result_set["title"]
        season = result_set.get("season", 0)
        episode = result_set.get("episode", 0)
        is_episodic = 0 < season < 1900 and not episode == 0
        if is_episodic:
            episode_text = None
            if " del " in name:
                name, episode_text = name.split(" del ", 1)
                episode_text = episode_text.lstrip("0123456789")

            if episode_text:
                episode_text = episode_text.lstrip(" -")
                name = "{} - s{:02d}e{:02d} - {}".format(name, season, episode, episode_text)
            else:
                name = "{} - s{:02d}e{:02d}".format(name, season, episode)

        item = MediaItem(name, url)
        item.description = result_set["description"]
        if item.description is None:
            item.description = item.name

        if is_episodic:
            item.set_season_info(season, episode)

        # premium_expire_date_time=2099-12-31T00:00:00+01:00
        expire_in_days = result_set.get("daysLeftInService", 0)
        if 0 < expire_in_days < 10000:
            item.set_expire_datetime(
                timestamp=datetime.datetime.now() + datetime.timedelta(days=expire_in_days))

        date = result_set["broadcastDateTime"]
        broadcast_date = DateHelper.get_datetime_from_string(date, "%Y-%m-%dT%H:%M:%SZ", "UTC")
        broadcast_date = broadcast_date.astimezone(self.__timezone)
        item.set_date(broadcast_date.year,
                      broadcast_date.month,
                      broadcast_date.day,
                      broadcast_date.hour,
                      broadcast_date.minute,
                      0)

        item.fanart = result_set.get("program_image", self.parentItem.fanart)
        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=70&resize=520x293&source={}" \
                .format(HtmlEntityHelper.url_encode(thumb_url))
        else:
            item.thumb = thumb_url

        item.type = "video"
        item.complete = False
        item.isGeoLocked = True
        # For now, none are paid.
        # item.isPaid = not result_set.get("freemium", False)
        if "drmProtected" in result_set:
            item.isDrmProtected = result_set["drmProtected"]
        elif "is_drm_protected" in result_set:
            item.isDrmProtected = result_set["is_drm_protected"]

        item.isLive = result_set.get("live", False)
        if item.isLive:
            item.name = "{:02d}:{:02d} - {}".format(broadcast_date.hour, broadcast_date.minute, name)
            item.url = "{0}&is_live=true".format(item.url)
        if item.isDrmProtected:
            item.url = "{}&drm=widevine&is_drm=true".format(item.url)

        item.set_info_label("duration", int(result_set.get("duration", 0)))
        return item