Пример #1
0
    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 list[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)

        item = MediaItem(result_set[0], result_set[1])
        item.type = "video"
        item.isGeoLocked = result_set[3].lower() == "true"

        date_time = DateHelper.get_date_from_posix(int(result_set[2]) * 1 / 1000)
        item.set_date(date_time.year, date_time.month, date_time.day, date_time.hour, date_time.minute,
                      date_time.second)

        thumb = result_set[4]
        if not thumb.startswith("http"):
            thumb = "%s%s" % (self.baseUrl, thumb)
        item.thumb = thumb

        return item
Пример #3
0
    def create_json_episode_item_sok(self, result_set):
        """ Creates a new MediaItem for search results.

        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 list[str]|dict result_set: The result_set of the self.episodeItemRegex

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

        """

        Logger.trace(result_set)
        url = result_set["url"]
        if url.startswith("/video") or url.startswith("/genre") or url.startswith('/oppetarkiv'):
            return None

        url = "%s%s" % (self.baseUrl, url, )
        item = MediaItem(result_set['title'], url)
        item.icon = self.icon
        item.thumb = result_set.get("thumbnail", self.noImage)
        if item.thumb.startswith("//"):
            item.thumb = "https:%s" % (item.thumb, )
        item.thumb = item.thumb.replace("/small/", "/large/")

        item.isGeoLocked = result_set.get('onlyAvailableInSweden', False)
        item.complete = True
        return item
Пример #4
0
    def create_json_episode_item(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 list[str]|dict result_set: The result_set of the self.episodeItemRegex

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

        """

        Logger.trace(result_set)

        if "titleArticleId" in result_set:
            return None

        url = "%s%s" % (self.baseUrl, result_set['contentUrl'],)
        if "/video/" in url:
            return None

        item = MediaItem(result_set['programTitle'], url)
        item.icon = self.icon
        item.isGeoLocked = result_set.get('onlyAvailableInSweden', False)
        item.description = result_set.get('description')

        thumb = self.noImage
        if "poster" in result_set:
            thumb = result_set["poster"]
            thumb = self.__get_thumb(thumb or self.noImage)

        item.thumb = thumb
        return item
Пример #5
0
    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
Пример #6
0
    def create_instalment_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,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

        """

        title = result_set["titles"]["title"]
        sub_title = result_set["titles"]["subtitle"]

        # noinspection PyTypeChecker
        if result_set.get("availability", {}).get("status",
                                                  "available") != "available":
            Logger.debug("Found '%s' with a non-available status", title)
            return None

        url = "https://psapi.nrk.no/programs/{}?apiKey={}".format(
            result_set["prfId"], self.__api_key)
        item = MediaItem(title, url)
        item.type = 'video'
        item.thumb = self.__get_image(result_set["image"], "width", "url")
        item.fanart = self.parentItem.fanart

        # noinspection PyTypeChecker
        item.isGeoLocked = result_set.get("usageRights", {}).get(
            "geoBlock", {}).get("isGeoBlocked", False)
        if sub_title and sub_title.strip():
            item.description = sub_title

        if "firstTransmissionDateDisplayValue" in result_set:
            Logger.trace("Using 'firstTransmissionDateDisplayValue' for date")
            day, month, year = result_set[
                "firstTransmissionDateDisplayValue"].split(".")
            item.set_date(year, month, day)
        elif "usageRights" in result_set and "from" in result_set[
                "usageRights"] and result_set["usageRights"][
                    "from"] is not None:
            Logger.trace("Using 'usageRights.from.date' for date")
            # noinspection PyTypeChecker
            date_value = result_set["usageRights"]["from"]["date"].split(
                "+")[0]
            time_stamp = DateHelper.get_date_from_string(
                date_value, date_format="%Y-%m-%dT%H:%M:%S")
            item.set_date(*time_stamp[0:6])

        return item
Пример #7
0
    def StievieCreateEpgItems(self, epg):
        Logger.Trace(epg)
        Logger.Debug("Processing EPG for channel %s", epg["id"])

        items = []
        summerTime = time.localtime().tm_isdst
        now = datetime.datetime.now()

        for resultSet in epg["items"]:
            # if not resultSet["parentSeriesOID"]:
            #     continue

            # Does not always work
            # videoId = resultSet["epgId"].replace("-", "_")
            # url = "https://vod.medialaan.io/vod/v2/videos/%s_Stievie_free" % (videoId, )
            videoId = resultSet["programOID"]
            url = "https://vod.medialaan.io/vod/v2/videos?episodeIds=%s&limit=10&offset=0&sort=broadcastDate&sortDirection=asc" % (videoId, )
            title = resultSet["title"]
            if resultSet["episode"] and resultSet["season"]:
                title = "%s - s%02de%02d" % (title, resultSet["season"], resultSet["episode"])

            if "startTime" in resultSet and resultSet["startTime"]:
                dateTime = resultSet["startTime"]
                dateValue = DateHelper.GetDateFromString(dateTime, dateFormat="%Y-%m-%dT%H:%M:%S.000Z")
                # Convert to Belgium posix time stamp
                dateValue2 = time.mktime(dateValue) + (1 + summerTime) * 60 * 60
                # Conver the posix to a time stamp
                startTime = DateHelper.GetDateFromPosix(dateValue2)

                title = "%02d:%02d - %s" % (startTime.hour, startTime.minute, title)

                # Check for items in their black-out period
                if "blackout" in resultSet and resultSet["blackout"]["enabled"]:
                    blackoutDuration = resultSet["blackout"]["duration"]
                    blackoutStart = startTime + datetime.timedelta(seconds=blackoutDuration)
                    if blackoutStart < now:
                        Logger.Debug("Found item in Black-out period: %s (started at %s)", title, blackoutStart)
                        continue

            # else:
            #     startTime = self.parentItem.metaData["airDate"]

            item = MediaItem(title, url)
            item.type = "video"
            item.isGeoLocked = resultSet["geoblock"]
            item.description = resultSet["shortDescription"]
            # item.SetDate(startTime.year, startTime.month, startTime.day)

            if "images" in resultSet and resultSet["images"] and "styles" in resultSet["images"][0]:
                images = resultSet["images"][0]["styles"]
                # if "1520x855" in images:
                #     item.fanart = images["1520x855"]
                if "400x225" in images:
                    item.thumb = images["400x225"]

            items.append(item)

        return items
Пример #8
0
    def create_json_genre_item(self, result_set):
        """ Creates a MediaItem of type 'folder/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.

        :param list[str]|dict result_set: The result_set of the self.episodeItemRegex

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

        """

        if "__typename" not in result_set:
            return None

        item_type = result_set["__typename"].lower()
        if item_type not in ("episode", "single", "clip", "tvseries") or "name" not in result_set:
            return None

        Logger.trace("%s->%s", item_type, result_set)
        title = result_set["name"]
        if item_type == 'episode' and "parent" in result_set:
            # noinspection PyTypeChecker
            parent_data = self.__apollo_data[result_set["parent"]["id"]]
            parent_title = parent_data["name"]
            title = "{} - {}".format(parent_title, title)

        if item_type == "clip":
            url = "https://www.svtplay.se/klipp/{}/".format(result_set["id"])
        elif "urls" in result_set:
            # noinspection PyTypeChecker
            url_data = self.__apollo_data[result_set["urls"]["id"]]
            url = url_data["svtplay"]
            url = "{}{}".format(self.baseUrl, url)
        else:
            Logger.debug("No url found for: %s", title)
            return None

        item = MediaItem(title, url)
        item.description = result_set.get("longDescription")
        item.fanart = self.parentItem.fanart
        item.type = "video" if item_type != "tvseries" else "folder"

        if "image" in result_set:
            # noinspection PyTypeChecker
            image = result_set["image"]["id"]
            image_data = self.__apollo_data[image]
            image_url = "https://www.svtstatic.se/image/medium/520/{id}/{changed}".format(**image_data)
            item.thumb = image_url

        if "restrictions" in result_set:
            # noinspection PyTypeChecker
            restrictions = self.__apollo_data[result_set["restrictions"]["id"]]
            item.isGeoLocked = restrictions.get('onlyAvailableInSweden', False)

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

        thumb_url = result_set[0]
        if thumb_url.startswith("//"):
            thumb_url = "http:%s" % (thumb_url, )
        elif not thumb_url.startswith("http"):
            thumb_url = "%s%s" % (self.baseUrl, thumb_url)
        Logger.trace(thumb_url)

        season = result_set[1]
        if season:
            name = "%s - %s" % (season, result_set[2])
        else:
            name = result_set[2]

        video_id = result_set[4]
        url = "http://www.oppetarkiv.se/video/%s?output=json" % (video_id, )
        item = MediaItem(name, url)
        item.type = 'video'
        item.icon = self.icon
        item.thumb = thumb_url

        date = result_set[5]
        date_key = 'datetime="'
        if date_key in date:
            date = date[date.index(date_key) + len(date_key):date.index("T")]
            date = date.split("-")
            year = date[0]
            month = date[1]
            day = date[2]
            Logger.trace("%s - %s-%s-%s", date, year, month, day)
            item.set_date(year, month, day)
        else:
            Logger.debug("No date found")

        item.complete = False
        item.isGeoLocked = True
        return item
Пример #10
0
    def create_category_item(self, result_set):
        """ Creates a MediaItem of type 'video/folder' 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,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)

        url = result_set["Url"]
        if "http://" not in url and "https://" not in url:
            url = "%s%s" % (self.baseUrl, url)

        thumb = result_set["Thumb"]
        if thumb.startswith("//"):
            thumb = "https:%s" % (thumb, )

        item = MediaItem(result_set['Title'], url)
        item.icon = self.icon
        item.thumb = thumb
        item.isGeoLocked = result_set["Abroad"] == "false"

        if result_set["Date1"] is not None and result_set["Date1"].lower(
        ) != "imorgon":
            year, month, day, hour, minutes = self.__get_date(
                result_set["Date1"], result_set["Date2"], result_set["Date3"])
            item.set_date(year, month, day, hour, minutes, 0)

        if "/video/" in url:
            item.type = "video"
            video_id = url.split("/")[4]
            item.url = "https://www.svtplay.se/video/%s?type=embed&output=json" % (
                video_id, )
        # else:
        #     # make sure we get the right tab for displaying
        #     item.url = "%s?tab=program" % (item.url, )

        return item
Пример #11
0
    def __create_json_episode_item(self, result_set, check_channel=True):
        """ 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 list[str]|dict[str,any] result_set: The result_set of the self.episodeItemRegex
        :param bool check_channel:                 Compare channel ID's and ignore that that do
                                                   not match.

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

        """

        Logger.trace(result_set)

        # make sure we use ID as GUID
        if "id" in result_set:
            result_set["guid"] = result_set["id"]

        if check_channel and self.channelId is not None:
            channels = [int(c["guid"]) for c in result_set.get("channels", [])]
            valid_channel_found = any(
                [c for c in channels if c in self.channelId])
            if not valid_channel_found:
                Logger.trace("Found item for wrong channel %s instead of %s",
                             channels, self.channelId)
                return None

        # For now we keep using the API, otherwise we need to do more complex VideoItem parsing
        if self.useNewPages:
            raise NotImplementedError("The 'slug' part is no longer working")
            # So this no longer works
            # category_slug = self.__categories[result_set["category"]]["guid"]
            # url = "%s/%s/%s" % (self.baseUrl, category_slug, result_set['slug'])
        else:
            url = "http://playapi.mtgx.tv/v3/videos?format=%(guid)s&order=-airdate&type=program" % result_set
        item = MediaItem(result_set['title'], url)
        item.icon = self.icon
        item.thumb = self.__get_thumb_image(
            result_set.get("image") or self.noImage)
        # No fanart for now
        # item.fanart = self.__get_thumb_image(resultSet.get("image") or self.fanart, fanartSize=True)

        item.isGeoLocked = result_set.get('onlyAvailableInSweden', False)
        return item
Пример #12
0
    def create_json_video(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|None] 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

        """

        video_id = result_set['id']

        # Categories to use
        # category = result_set["maincategory"].title()
        # subcategory = result_set["subcategory"].title()

        url = "https://api.nos.nl/mobile/video/%s/phone.json" % (video_id, )
        item = MediaItem(result_set['title'], url, type="video")
        item.icon = self.icon
        if 'image' in result_set:
            images = result_set['image']["formats"]
            matched_image = images[-1]
            for image in images:
                if image["width"] >= 720:
                    matched_image = image
                    break
            item.thumb = matched_image["url"].values()[0]

        item.description = result_set["description"]
        item.complete = False
        item.isGeoLocked = result_set.get("geoprotection", False)

        # set the date and time
        date = result_set["published_at"]
        time_stamp = DateHelper.get_date_from_string(date, date_format="%Y-%m-%dT%H:%M:%S+{0}".format(date[-4:]))
        item.set_date(*time_stamp[0:6])
        return item
Пример #13
0
    def create_series_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

        """

        title = result_set["title"]
        sub_title = result_set.get("episodeTitle", None)
        if sub_title:
            title = "{} - {}".format(title, sub_title)

        if not result_set["usageRights"].get("hasRightsNow", True):
            Logger.debug("Found '%s' without 'usageRights'", title)
            return None

        url = "https://psapi.nrk.no/programs/{}?apiKey={}".format(
            result_set["id"], self.__api_key)
        item = MediaItem(title, url)
        item.type = 'video'

        # noinspection PyTypeChecker
        item.thumb = self.__get_image(result_set["image"]["webImages"],
                                      "pixelWidth", "imageUrl")
        item.description = result_set.get("longDescription", "")
        if not item.description:
            item.description = result_set.get("shortDescription", "")

        item.isGeoLocked = result_set.get("usageRights",
                                          {}).get("isGeoBlocked", False)
        self.__set_date(result_set, item)
        return item
Пример #14
0
    def __create_generic_item(self, result_set, expected_item_type,
                              url_format):
        video_info = result_set["attributes"]
        name = video_info["name"]

        if expected_item_type != result_set["type"]:
            Logger.warning("Not %s, excluding %s", expected_item_type, name)
            return None

        channel_id = int(
            result_set["relationships"]["primaryChannel"]["data"]["id"])
        if self.primaryChannelId is not None and channel_id != self.primaryChannelId:
            return None

        item_id = result_set["id"]
        # Show the slug?
        # showSlug = video_info["alternateId"]

        url = url_format.format(item_id)
        item = MediaItem(name, url)
        item.description = video_info.get("description")

        geo_info = video_info.get("geoRestrictions", {"countries": ["world"]})
        item.isGeoLocked = "world" not in geo_info.get("countries")

        # set the images
        if "images" in result_set["relationships"]:
            thumb_id = result_set["relationships"]["images"]["data"][0]["id"]
            item.thumb = self.imageLookup.get(thumb_id, self.noImage)
            if item.thumb == self.noImage:
                Logger.warning("No thumb found for %s", thumb_id)

        # paid or not?
        if "contentPackages" in result_set["relationships"]:
            item.isPaid = not any(
                filter(lambda p: p["id"].lower() == "free",
                       result_set["relationships"]["contentPackages"]["data"]))
        else:
            item.isPaid = False

        return item
    def create_episode_item(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 list[str]|dict[str,str] result_set: The result_set of the self.episodeItemRegex

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

        """

        Logger.trace(result_set)

        genres = result_set[0]
        if self.__genre and self.__genre not in genres:
            Logger.debug("Item '%s' filtered due to genre: %s", result_set[2],
                         genres)
            return None

        url = result_set[1]
        if "&" in url:
            url = HtmlEntityHelper.convert_html_entities(url)

        if not url.startswith("http:"):
            url = "%s%s" % (self.baseUrl, url)

        # get the ajax page for less bandwidth
        url = "%s?sida=1&amp;sort=tid_stigande&embed=true" % (url, )

        item = MediaItem(result_set[2], url)
        item.icon = self.icon
        item.thumb = self.noImage
        item.complete = True
        item.isGeoLocked = True
        return item
Пример #16
0
    def get_live_items(self, data):
        """ Adds live stream items.

        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("Fetching episode items")
        items = []

        live_items = MediaItem("\a.: Live TV :.", "")
        live_items.thumb = self.noImage
        live_items.icon = self.icon
        items.append(live_items)

        live_base = "http://il.srgssr.ch/integrationlayer/1.0/ue/srf/video/play/%s.json"
        live_channels = {
            "SRF 1 live": ("c4927fcf-e1a0-0001-7edd-1ef01d441651", "srf1.png"),
            "SRF zwei live":
            ("c49c1d64-9f60-0001-1c36-43c288c01a10", "srf2.png"),
            "SRF info live":
            ("c49c1d73-2f70-0001-138a-15e0c4ccd3d0", "srfinfo.png")
        }
        for live_item in live_channels.keys():
            item = MediaItem(live_item,
                             live_base % (live_channels[live_item][0], ))
            item.thumb = self.get_image_location(live_channels[live_item][1])
            item.icon = self.icon
            item.isGeoLocked = True
            item.type = "video"
            live_items.items.append(item)

        return data, items
Пример #17
0
    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
Пример #18
0
    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
Пример #19
0
    def create_generic_item(self, result_set, program_type):
        """ Creates a MediaItem of type 'video' or 'folder' using the result_set from the regex and
        a basic set of values.

        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

        """

        title = result_set["title"]

        if not result_set.get("hasOndemandRights", True):
            Logger.debug("Item '%s' has no on-demand rights", title)
            return None

        item_id = result_set["id"]
        if program_type == "programme":
            url = "https://psapi.nrk.no/programs/{}?apiKey={}".format(
                item_id, self.__api_key)
            item = MediaItem(title, url)
            item.type = 'video'
        else:
            use_old_series_api = False
            if use_old_series_api:
                url = "https://psapi.nrk.no/series/{}?apiKey={}".format(
                    item_id, self.__api_key)
            else:
                url = "https://psapi.nrk.no/tv/catalog/series/{}?apiKey={}".format(
                    item_id, self.__api_key)

            item = MediaItem(title, url)
            item.type = 'folder'

        item.icon = self.icon
        item.isGeoLocked = result_set.get(
            "isGeoBlocked",
            result_set.get("usageRights", {}).get("isGeoBlocked", False))

        description = result_set.get("description")
        if description and description.lower() != "no description":
            item.description = description

        if "image" not in result_set or "webImages" not in result_set["image"]:
            return item

        # noinspection PyTypeChecker
        item.thumb = self.__get_image(result_set["image"]["webImages"],
                                      "pixelWidth", "imageUrl")

        # see if there is a date?
        self.__set_date(result_set, item)
        return item
Пример #20
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,dict|None] 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"]
        if "subTitle" in result_set:
            title = "%s - %s" % (title, result_set["subTitle"])
        mgid = result_set["id"].split(":")[-1]
        url = "http://feeds.mtvnservices.com/od/feed/intl-mrss-player-feed" \
              "?mgid=mgid:arc:episode:mtvplay.com:%s" \
              "&ep=%s" \
              "&episodeType=segmented" \
              "&imageEp=android.playplex.mtv.%s" \
              "&arcEp=android.playplex.mtv.%s" \
              % (mgid, self.__backgroundServiceEp, self.__region.lower(), self.__region.lower())

        item = MediaItem(title, url)
        item.type = "video"
        item.icon = self.icon
        item.description = result_set.get("description", None)

        item.thumb = self.parentItem.thumb
        item.fanart = self.parentItem.fanart
        item.isGeoLocked = True
        images = result_set.get("images", [])
        if images:
            # mgid:file:gsp:scenic:/international/mtv.nl/playplex/dutch-ridiculousness/Dutch_Ridiculousness_Landscape.png
            # http://playplex.mtvnimages.com/uri/mgid:file:gsp:scenic:/international/mtv.nl/playplex/dutch-ridiculousness/Dutch_Ridiculousness_Landscape.png
            for image in images:
                if image["width"] > 500:
                    pass  # no fanart here
                else:
                    item.thumb = "http://playplex.mtvnimages.com/uri/%(url)s" % image

        date = result_set.get("originalAirDate", None)
        if not date:
            date = result_set.get("originalPublishDate", None)
        if date:
            time_stamp = date["timestamp"]
            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
Пример #21
0
    def create_recent_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(result_set)

        show_title = result_set["abstract_name"]
        episode_title = result_set["title"]
        title = "{} - {}".format(show_title, episode_title)
        description = result_set.get("synopsis")

        uuid = result_set["uuid"]
        url = "http://www.rtl.nl/system/s4m/xldata/ux/%s?context=rtlxl&" \
              "d=pc&fmt=adaptive&version=3" % (uuid, )
        # The JSON urls do not yet work
        # url = "http://www.rtl.nl/system/s4m/vfd/version=1/d=pc/output=json/" \
        #       "fun=abstract/uuid=%s/fmt=smooth" % (uuid,)

        item = MediaItem(title.title(), url)
        item.type = "video"
        item.description = description
        item.thumb = "%s%s" % (
            self.posterBase,
            uuid,
        )

        audience = result_set.get("audience")
        Logger.debug("Found audience: %s", audience)
        item.isGeoLocked = audience == "ALLEEN_NL"
        # We can play the DRM stuff
        # item.isDrmProtected = audience == "DRM"

        station = result_set.get("station", None)
        if station:
            item.name = "{} ({})".format(item.name, station)
            icon = self.largeIconSet.get(station.lower(), None)
            if icon:
                Logger.trace("Setting icon to: %s", icon)
                item.icon = icon

        # 2018-12-05T19:30:00.000Z
        date_time = result_set.get("dateTime", None)
        if date_time:
            date_time = DateHelper.get_date_from_string(
                date_time[:-5], "%Y-%m-%dT%H:%M:%S")
            # The time is in UTC, and the show as at UTC+1
            date_time = datetime.datetime(*date_time[:6]) + datetime.timedelta(
                hours=1)
            item.name = "{:02d}:{:02d}: {}".format(date_time.hour,
                                                   date_time.minute, item.name)
            item.set_date(date_time.year, date_time.month, date_time.day,
                          date_time.hour, date_time.minute, date_time.second)
        return item
Пример #22
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
Пример #23
0
    def create_json_item(self, result_set):  # NOSONAR
        """ 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(result_set)

        # determine the title
        program_title = result_set.get("programTitle", "") or ""
        show_title = result_set.get("title", "") or ""
        if show_title == "" and program_title != "":
            title = program_title
        elif show_title != "" and program_title == "":
            title = show_title
        elif program_title == "" and show_title == "":
            Logger.warning("Could not find title for item: %s", result_set)
            return None
        elif show_title != "" and show_title != program_title:
            title = "%s - %s" % (program_title, show_title)
        else:
            # they are the same
            title = show_title  # NOSONAR

        if "live" in result_set and result_set["live"]:
            title = "%s (&middot;Live&middot;)" % (title, )

        item_type = result_set.get("contentType")
        if "contentUrl" in result_set:
            if "versions" in result_set and bool(result_set["versions"]):
                video_id = result_set["versions"][0]["id"]
            else:
                video_id = result_set["id"]
            url = "https://api.svt.se/videoplayer-api/video/{}".format(
                video_id)
        else:
            url = result_set["url"]
        broad_cast_date = result_set.get("broadcastDate", None)

        if item_type in ("videoEpisod", "videoKlipp", "singel"):
            if "/video/" not in url and "/klipp/" not in url:
                Logger.warning(
                    "Found video item without a /video/ or /klipp/ url.")
                return None
            item_type = "video"
            if "programVersionId" in result_set:
                url = "https://www.svt.se/videoplayer-api/video/%s" % (
                    result_set["programVersionId"], )
            elif not url.startswith("http"):
                url = "%s%s" % (self.baseUrl, url)
        else:
            item_type = "folder"
            url = "%s%s" % (self.baseUrl, url)

        item = MediaItem(title, url)
        item.icon = self.icon
        item.type = item_type
        item.isGeoLocked = result_set.get("onlyAvailableInSweden", False)
        item.description = result_set.get("description", "")

        if "season" in result_set and "episodeNumber" in result_set and result_set[
                "episodeNumber"]:
            season = int(result_set["season"])
            episode = int(result_set["episodeNumber"])
            if season > 0 and episode > 0:
                item.name = "s%02de%02d - %s" % (season, episode, item.name)
                item.set_season_info(season, episode)

        thumb = self.noImage
        if self.parentItem:
            thumb = self.parentItem.thumb

        for image_key in ("image", "imageMedium", "thumbnailMedium",
                          "thumbnail", "poster"):
            if image_key in result_set and result_set[image_key] is not None:
                thumb = result_set[image_key]
                break

        item.thumb = self.__get_thumb(thumb or self.noImage)

        if broad_cast_date is not None:
            if "+" in broad_cast_date:
                broad_cast_date = broad_cast_date.rsplit("+")[0]
            time_stamp = DateHelper.get_date_from_string(
                broad_cast_date, "%Y-%m-%dT%H:%M:%S")
            item.set_date(*time_stamp[0:6])

        # Set the expire date
        expire_date = result_set.get("expireDate")
        if expire_date is not None:
            expire_date = expire_date.split("+")[0].replace("T", " ")
            year = expire_date.split("-")[0]
            if len(year
                   ) == 4 and int(year) < datetime.datetime.now().year + 50:
                item.description = \
                    "{}\n\n{}: {}".format(item.description or "", self.__expires_text, expire_date)

        length = result_set.get("materialLength", 0)
        if length > 0:
            item.set_info_label(MediaItem.LabelDuration, length)
        return item
Пример #24
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