Ejemplo n.º 1
0
    def __send_log(self):
        """ Send log files via Pastbin or Gist. """

        from resources.lib.helpers.logsender import LogSender
        sender_mode = 'hastebin'
        log_sender = LogSender(Config.logSenderApi,
                               logger=Logger.instance(),
                               mode=sender_mode)
        try:
            title = LanguageHelper.get_localized_string(
                LanguageHelper.LogPostSuccessTitle)
            url_text = LanguageHelper.get_localized_string(
                LanguageHelper.LogPostLogUrl)
            files_to_send = [
                Logger.instance().logFileName,
                Logger.instance().logFileName.replace(".log", ".old.log")
            ]
            if sender_mode != "gist":
                paste_url = log_sender.send_file(Config.logFileNameAddon,
                                                 files_to_send[0])
            else:
                paste_url = log_sender.send_files(Config.logFileNameAddon,
                                                  files_to_send)
            XbmcWrapper.show_dialog(title, url_text % (paste_url, ))
        except Exception as e:
            Logger.error("Error sending %s",
                         Config.logFileNameAddon,
                         exc_info=True)

            title = LanguageHelper.get_localized_string(
                LanguageHelper.LogPostErrorTitle)
            error_text = LanguageHelper.get_localized_string(
                LanguageHelper.LogPostError)
            error = error_text % (str(e), )
            XbmcWrapper.show_dialog(title, error.strip(": "))
Ejemplo n.º 2
0
    def __show_first_time_message(self, channel_info):
        """ Checks if it is the first time a channel is executed and if a first time message is
        available it will be shown.

        Shows a message dialog if the message should be shown.  Make sure that each line fits
        in a single line of a Kodi Dialog box (50 chars).

        :param ChannelInfo channel_info:    The ChannelInfo to show a message for.

        """

        hide_first_time = AddonSettings.hide_first_time_messages()
        if channel_info.firstTimeMessage:
            if not hide_first_time:
                Logger.info(
                    "Showing first time message '%s' for channel chn_%s.",
                    channel_info.firstTimeMessage, channel_info.moduleName)

                title = LanguageHelper.get_localized_string(
                    LanguageHelper.ChannelMessageId)
                XbmcWrapper.show_dialog(
                    title, channel_info.firstTimeMessage.split("|"))
            else:
                Logger.debug(
                    "Not showing first time message due to add-on setting set to '%s'.",
                    hide_first_time)
        return
Ejemplo n.º 3
0
    def toggle_cloak(self):
        """ Toggles the cloaking (showing/hiding) of the selected folder. """

        item = self._pickler.de_pickle_media_item(
            self.params[self.keywordPickle])
        Logger.info("Cloaking current item: %s", item)
        c = Cloaker(self.channelObject,
                    AddonSettings.store(LOCAL),
                    logger=Logger.instance())

        if c.is_cloaked(item.url):
            c.un_cloak(item.url)
            self.refresh()
            return

        first_time = c.cloak(item.url)
        if first_time:
            XbmcWrapper.show_dialog(
                LanguageHelper.get_localized_string(
                    LanguageHelper.CloakFirstTime),
                LanguageHelper.get_localized_string(
                    LanguageHelper.CloakMessage))

        del c
        self.refresh()
Ejemplo n.º 4
0
    def log_on(self):
        """ Logs on to a website, using an url.

        First checks if the channel requires log on. If so and it's not already
        logged on, it should handle the log on. That part should be implemented
        by the specific channel.

        More arguments can be passed on, but must be handled by custom code.

        After a successful log on the self.loggedOn property is set to True and
        True is returned.

        :return: indication if the login was successful.
        :rtype: bool

        """

        if self.__idToken:
            return True

        # check if there is a refresh token
        # refresh token: viervijfzes_refresh_token
        refresh_token = AddonSettings.get_setting("viervijfzes_refresh_token")
        client = AwsIdp("eu-west-1_dViSsKM5Y",
                        "6s1h851s8uplco5h6mqh1jac8m",
                        proxy=self.proxy,
                        logger=Logger.instance())
        if refresh_token:
            id_token = client.renew_token(refresh_token)
            if id_token:
                self.__idToken = id_token
                return True
            else:
                Logger.info("Extending token for VierVijfZes failed.")

        # username: viervijfzes_username
        username = AddonSettings.get_setting("viervijfzes_username")
        # password: viervijfzes_password
        v = Vault()
        password = v.get_setting("viervijfzes_password")
        if not username or not password:
            XbmcWrapper.show_dialog(
                title=None,
                lines=LanguageHelper.get_localized_string(
                    LanguageHelper.MissingCredentials),
            )
            return False

        id_token, refresh_token = client.authenticate(username, password)
        if not id_token or not refresh_token:
            Logger.error("Error getting a new token. Wrong password?")
            return False

        self.__idToken = id_token
        AddonSettings.set_setting("viervijfzes_refresh_token", refresh_token)
        return True
Ejemplo n.º 5
0
    def update_video_item(self, item):
        """ Updates an existing MediaItem with more data.

        Used to update none complete MediaItems (self.complete = False). This
        could include opening the item's URL to fetch more data and then process that
        data or retrieve it's real media-URL.

        The method should at least:
        * cache the thumbnail to disk (use self.noImage if no thumb is available).
        * set at least one MediaItemPart with a single MediaStream.
        * set self.complete = True.

        if the returned item does not have a MediaItemPart then the self.complete flag
        will automatically be set back to False.

        :param MediaItem item: the original MediaItem that needs updating.

        :return: The original item with more data added to it's properties.
        :rtype: MediaItem

        """

        Logger.debug('Starting update_video_item for %s (%s)', item.name, self.channelName)

        if "index.html" in item.url:
            data = UriHandler.open(
                item.url,
                additional_headers={"Referer": "http://www.{}/".format(self.__country_id)}
            )
            json_data = JsonHelper(data)
            guid = json_data.get_value("feed", "items", 0, "guid")
            url = "https://media-utils.mtvnservices.com/services/MediaGenerator/" \
                  "{}?arcStage=live&format=json&acceptMethods=hls&clang=nl" \
                  "&https=true".format(guid)
        else:
            url = item.url

        data = UriHandler.open(url)
        json_data = JsonHelper(data)
        url = json_data.get_value("package", "video", "item", 0, "rendition", 0, "src")
        if not url:
            error = json_data.get_value("package", "video", "item", 0, "text")
            Logger.error("Error resolving url: %s", error)
            XbmcWrapper.show_dialog(LanguageHelper.ErrorId, error)
            return item

        item.MediaItemParts = []
        part = item.create_new_empty_media_part()
        part.append_media_stream(url, 0)
        item.complete = True
        return item
Ejemplo n.º 6
0
    def __update_video_from_mpd(self, item, mpd_info,
                                use_adaptive_with_encryption):
        """ Updates an existing MediaItem with more data based on an MPD stream.

        :param dict[str,str] mpd_info:              Stream info retrieved from the stream json.
        :param bool use_adaptive_with_encryption:   Do we use the Adaptive InputStream add-on?
        :param MediaItem item:                      The original MediaItem that needs updating.

        :return: The original item with more data added to it's properties.
        :rtype: MediaItem

        """

        Logger.debug("Updating streams using BrightCove data.")

        part = item.create_new_empty_media_part()
        mpd_manifest_url = "https:{0}".format(mpd_info["mediaLocator"])
        mpd_data = UriHandler.open(mpd_manifest_url, proxy=self.proxy)
        subtitles = Regexer.do_regex(r'<BaseURL>([^<]+\.vtt)</BaseURL>',
                                     mpd_data)

        if subtitles:
            Logger.debug("Found subtitle: %s", subtitles[0])
            subtitle = SubtitleHelper.download_subtitle(subtitles[0],
                                                        proxy=self.proxy,
                                                        format="webvtt")
            part.Subtitle = subtitle

        if use_adaptive_with_encryption:
            # We can use the adaptive add-on with encryption
            Logger.info("Using MPD InputStreamAddon")
            license_url = Regexer.do_regex('licenseUrl="([^"]+)"', mpd_data)[0]
            token = "Bearer {0}".format(mpd_info["playToken"])
            key_headers = {"Authorization": token}
            license_key = Mpd.get_license_key(license_url,
                                              key_headers=key_headers)

            stream = part.append_media_stream(mpd_manifest_url, 0)
            Mpd.set_input_stream_addon_input(stream,
                                             self.proxy,
                                             license_key=license_key)
            item.complete = True
        else:
            XbmcWrapper.show_dialog(
                LanguageHelper.get_localized_string(LanguageHelper.DrmTitle),
                LanguageHelper.get_localized_string(
                    LanguageHelper.WidevineLeiaRequired))

        return item
Ejemplo n.º 7
0
    def __show_warnings(self, media_item):
        """ Show playback warnings for this MediaItem

        :param MediaItem media_item: The current MediaItem that will be played.

        """

        if (media_item.isDrmProtected or media_item.isPaid) and AddonSettings.show_drm_paid_warning():
            if media_item.isDrmProtected:
                Logger.debug("Showing DRM Warning message")
                title = LanguageHelper.get_localized_string(LanguageHelper.DrmTitle)
                message = LanguageHelper.get_localized_string(LanguageHelper.DrmText)
                XbmcWrapper.show_dialog(title, message)
            elif media_item.isPaid:
                Logger.debug("Showing Paid Warning message")
                title = LanguageHelper.get_localized_string(LanguageHelper.PaidTitle)
                message = LanguageHelper.get_localized_string(LanguageHelper.PaidText)
                XbmcWrapper.show_dialog(title, message)
Ejemplo n.º 8
0
    def process_video_item(self, item):
        """ Process a video item using the required dataparsers

        :param MediaItem item:    The Item to update

        :return: An updated item.
        :rtype: MediaItem

        """

        data_parsers = self.__get_data_parsers(item.url)
        if not data_parsers:
            Logger.error("No dataparsers found cannot update item.")
            return item

        data_parsers = [d for d in data_parsers if d.Updater is not None]
        if len(data_parsers) < 1:
            Logger.warning("No DataParsers with Updaters found.")
            return item

        if len(data_parsers) > 1:
            Logger.warning(
                "More than 2 DataParsers with Updaters found. Only using first one."
            )
        data_parser = data_parsers[0]

        if not data_parser.Updater:
            Logger.error("No videoupdater found cannot update item.")
            return item

        if data_parser.LogOnRequired:
            Logger.info("One or more dataparsers require logging in.")
            self.loggedOn = self.log_on()
            if not self.loggedOn:
                Logger.warning("Could not log on for: %s", self)
                title = LanguageHelper.get_localized_string(
                    LanguageHelper.LoginErrorTitle)
                text = LanguageHelper.get_localized_string(
                    LanguageHelper.LoginErrorText)
                XbmcWrapper.show_dialog(title, text)

        Logger.debug("Processing Updater from %s", data_parser)
        return data_parser.Updater(item)
Ejemplo n.º 9
0
    def __update_dash_video(self, item, stream_info):
        """

        :param MediaItem item:          The item that was updated
        :param JsonHelper stream_info:  The stream info
        """

        if not AddonSettings.use_adaptive_stream_add_on(with_encryption=True):
            XbmcWrapper.show_dialog(
                LanguageHelper.get_localized_string(LanguageHelper.DrmTitle),
                LanguageHelper.get_localized_string(
                    LanguageHelper.WidevineLeiaRequired))
            return item

        playback_item = stream_info.get_value("playbackItem")

        stream_url = playback_item["manifestUrl"]
        part = item.create_new_empty_media_part()
        stream = part.append_media_stream(stream_url, 0)

        license_info = playback_item.get("license", None)
        if license_info is not None:
            license_key_token = license_info["token"]
            auth_token = license_info["castlabsToken"]
            header = {
                "x-dt-auth-token": auth_token,
                "content-type": "application/octstream"
            }
            license_url = license_info["castlabsServer"]
            license_key = Mpd.get_license_key(license_url,
                                              key_value=license_key_token,
                                              key_headers=header)

            Mpd.set_input_stream_addon_input(stream,
                                             proxy=self.proxy,
                                             license_key=license_key)
            item.isDrmProtected = False
        else:
            Mpd.set_input_stream_addon_input(stream, proxy=self.proxy)

        item.complete = True
        return item
Ejemplo n.º 10
0
    def __update_embedded_video(self, item):
        """ Updates video items that are encrypted. This could be the default for Krypton!

        :param MediaItem item: The item to update.

        :return: An updated item.
        :rtype: MediaItem

        """

        data = UriHandler.open(item.url, proxy=self.proxy)
        if UriHandler.instance().status.code == 404:
            title, message = Regexer.do_regex(
                r'<h1>([^<]+)</h1>\W+<p>([^<]+)<', data)[0]
            XbmcWrapper.show_dialog(title, message)
            return item

        start_needle = "var playerConfig ="
        start_data = data.index(start_needle) + len(start_needle)
        end_data = data.index("var talpaPlayer")
        data = data[start_data:end_data].strip().rstrip(";")

        json = JsonHelper(data)
        has_drm_only = True
        adaptive_available = AddonSettings.use_adaptive_stream_add_on(
            with_encryption=False, channel=self)
        adaptive_available_encrypted = AddonSettings.use_adaptive_stream_add_on(
            with_encryption=True, channel=self)

        for play_list_entry in json.get_value("playlist"):
            part = item.create_new_empty_media_part()
            for source in play_list_entry["sources"]:
                stream_type = source["type"]
                stream_url = source["file"]
                stream_drm = source.get("drm")

                if not stream_drm:
                    has_drm_only = False
                    if stream_type == "m3u8":
                        Logger.debug("Found non-encrypted M3u8 stream: %s",
                                     stream_url)
                        M3u8.update_part_with_m3u8_streams(part,
                                                           stream_url,
                                                           proxy=self.proxy,
                                                           channel=self)
                        item.complete = True
                    elif stream_type == "dash" and adaptive_available:
                        Logger.debug("Found non-encrypted Dash stream: %s",
                                     stream_url)
                        stream = part.append_media_stream(stream_url, 1)
                        Mpd.set_input_stream_addon_input(stream,
                                                         proxy=self.proxy)
                        item.complete = True
                    else:
                        Logger.debug("Unknown stream source: %s", source)

                else:
                    compatible_drm = "widevine"
                    if compatible_drm not in stream_drm or stream_type != "dash":
                        Logger.debug("Found encrypted %s stream: %s",
                                     stream_type, stream_url)
                        continue

                    Logger.debug("Found Widevine encrypted Dash stream: %s",
                                 stream_url)
                    license_url = stream_drm[compatible_drm]["url"]
                    pid = stream_drm[compatible_drm]["releasePid"]
                    encryption_json = '{"getRawWidevineLicense":' \
                                      '{"releasePid":"%s", "widevineChallenge":"b{SSM}"}' \
                                      '}' % (pid,)

                    headers = {
                        "Content-Type": "application/json",
                        "Origin": "https://embed.kijk.nl",
                        "Referer": stream_url
                    }

                    encryption_key = Mpd.get_license_key(
                        license_url,
                        key_type=None,
                        key_value=encryption_json,
                        key_headers=headers)

                    stream = part.append_media_stream(stream_url, 0)
                    Mpd.set_input_stream_addon_input(
                        stream, proxy=self.proxy, license_key=encryption_key)
                    item.complete = True

            subs = [
                s['file'] for s in play_list_entry.get("tracks", [])
                if s.get('kind') == "captions"
            ]
            if subs:
                subtitle = SubtitleHelper.download_subtitle(subs[0],
                                                            format="webvtt")
                part.Subtitle = subtitle

        if has_drm_only and not adaptive_available_encrypted:
            XbmcWrapper.show_dialog(
                LanguageHelper.get_localized_string(LanguageHelper.DrmTitle),
                LanguageHelper.get_localized_string(
                    LanguageHelper.WidevineLeiaRequired))
        return item
Ejemplo n.º 11
0
    def update_video_item(self, item):
        """ Updates an existing MediaItem with more data.

        Used to update none complete MediaItems (self.complete = False). This
        could include opening the item's URL to fetch more data and then process that
        data or retrieve it's real media-URL.

        The method should at least:
        * cache the thumbnail to disk (use self.noImage if no thumb is available).
        * set at least one MediaItemPart with a single MediaStream.
        * set self.complete = True.

        if the returned item does not have a MediaItemPart then the self.complete flag
        will automatically be set back to False.

        :param MediaItem item: the original MediaItem that needs updating.

        :return: The original item with more data added to it's properties.
        :rtype: MediaItem

        """

        if item.metaData.get(self.__REQUIRES_LOGIN, False):
            logged_in = self.log_on()
            if not logged_in:
                XbmcWrapper.show_dialog(LanguageHelper.LoginErrorTitle,
                                        LanguageHelper.LoginErrorText)
                return item

        video_data = UriHandler.open(item.url,
                                     proxy=self.proxy,
                                     additional_headers=self.localIP)
        if not video_data:
            return item

        video_data = JsonHelper(video_data)
        video_info = video_data.get_value("data", "attributes")
        errors = video_data.get_value("errors")
        Logger.error("Error updating items: %s", errors)
        if errors:
            return item

        part = item.create_new_empty_media_part()

        m3u8url = video_info["streaming"]["hls"]["url"]

        m3u8data = UriHandler.open(m3u8url, self.proxy)
        if AddonSettings.use_adaptive_stream_add_on():
            stream = part.append_media_stream(m3u8url, 0)
            item.complete = True
            M3u8.set_input_stream_addon_input(stream, self.proxy)
        else:
            # user agent for all sub m3u8 and ts requests needs to be the same
            part.HttpHeaders[
                "user-agent"] = "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-GB; rv:1.9.2.13) Gecko/20101203 Firefox/3.6.13 (.NET CLR 3.5.30729)"
            for s, b, a in M3u8.get_streams_from_m3u8(
                    m3u8url,
                    self.proxy,
                    append_query_string=False,
                    map_audio=True,
                    play_list_data=m3u8data):
                item.complete = True
                if a:
                    audio_part = a.split("-prog_index.m3u8", 1)[0]
                    audio_id = audio_part.rsplit("/", 1)[-1]
                    s = s.replace("-prog_index.m3u8",
                                  "-{0}-prog_index.m3u8".format(audio_id))
                part.append_media_stream(s, b)

        if self.language == "se":
            vtt_url = M3u8.get_subtitle(m3u8url,
                                        self.proxy,
                                        m3u8data,
                                        language="sv")
        elif self.language == "dk":
            vtt_url = M3u8.get_subtitle(m3u8url,
                                        self.proxy,
                                        m3u8data,
                                        language="da")
        else:
            vtt_url = M3u8.get_subtitle(m3u8url, self.proxy, m3u8data)

        # https://dplaynordics-vod-80.akamaized.net/dplaydni/259/0/hls/243241001/1112635959-prog_index.m3u8?version_hash=bb753129&hdnts=st=1518218118~exp=1518304518~acl=/*~hmac=bdeefe0ec880f8614e14af4d4a5ca4d3260bf2eaa8559e1eb8ba788645f2087a
        vtt_url = vtt_url.replace("-prog_index.m3u8", "-0.vtt")
        part.Subtitle = SubtitleHelper.download_subtitle(vtt_url,
                                                         format='srt',
                                                         proxy=self.proxy)

        # if the user has premium, don't show any warnings
        if self.__has_premium:
            item.isPaid = False
        return item