def __fetch_textures(self):
        textures_to_retrieve = TextureHandler.instance(
        ).number_of_missing_textures()

        if textures_to_retrieve > 0:
            w = None
            try:
                # show a blocking or background progress bar
                if textures_to_retrieve > 4:
                    w = XbmcDialogProgressWrapper(
                        "%s: %s" % (Config.appName,
                                    LanguageHelper.get_localized_string(
                                        LanguageHelper.InitChannelTitle)),
                        LanguageHelper.get_localized_string(
                            LanguageHelper.FetchTexturesTitle),
                        # Config.textureUrl
                    )
                else:
                    w = XbmcDialogProgressBgWrapper(
                        "%s: %s" % (Config.appName,
                                    LanguageHelper.get_localized_string(
                                        LanguageHelper.FetchTexturesTitle)),
                        Config.textureUrl)

                TextureHandler.instance().fetch_textures(w.progress_update)
            except:
                Logger.error("Error fetching textures", exc_info=True)
            finally:
                if w is not None:
                    # always close the progress bar
                    w.close()
        return
    def __send_log(self):
        """ Send log files via Pastbin or Gist. """

        from 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(": "))
Exemple #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()
Exemple #4
0
    def __get_application_key(self):
        """ Gets the decrypted application key that is used for all the encryption.

        :return: The decrypted application key that is used for all the encryption.
        :rtype: bytes

        """

        application_key_encrypted = AddonSettings.get_setting(
            Vault.__APPLICATION_KEY_SETTING, store=LOCAL)
        # The key was never in the local store the value was None. It was "" if it was reset.
        if application_key_encrypted is None:
            application_key_encrypted = AddonSettings.get_setting(
                Vault.__APPLICATION_KEY_SETTING, store=KODI)
            if not application_key_encrypted:
                return None

            Logger.info("Moved ApplicationKey to local storage")
            AddonSettings.set_setting(Vault.__APPLICATION_KEY_SETTING,
                                      application_key_encrypted,
                                      store=LOCAL)

        # Still no application key? Then there was no key!
        if application_key_encrypted == "" or application_key_encrypted is None:
            return None

        vault_incorrect_pin = LanguageHelper.get_localized_string(
            LanguageHelper.VaultIncorrectPin)
        pin = XbmcWrapper.show_key_board(
            heading=LanguageHelper.get_localized_string(
                LanguageHelper.VaultInputPin),
            hidden=True)
        if not pin:
            XbmcWrapper.show_notification("", vault_incorrect_pin,
                                          XbmcWrapper.Error)
            raise RuntimeError("Incorrect Retrospect PIN specified")
        pin_key = self.__get_pbk(pin)
        application_key = self.__decrypt(application_key_encrypted, pin_key)
        if not application_key.startswith(Vault.__APPLICATION_KEY_SETTING):
            Logger.critical("Invalid Retrospect PIN")
            XbmcWrapper.show_notification("", vault_incorrect_pin,
                                          XbmcWrapper.Error)
            raise RuntimeError("Incorrect Retrospect PIN specified")

        application_key_value = application_key[
            len(Vault.__APPLICATION_KEY_SETTING) + 1:]
        Logger.info("Successfully decrypted the ApplicationKey.")
        if PY2:
            return application_key_value

        # We return bytes on Python 3
        return application_key_value.encode()
Exemple #5
0
    def __update_title_and_description_with_limitations(self):
        """ Updates the title/name and description with the symbols for DRM, GEO and Paid.

        :return:            (tuple) name postfix, description postfix
        :rtype: tuple[str,str]

        """

        geo_lock = "º"  # º
        drm_lock = "^"  # ^
        paid = "ª"  # ª
        cloaked = "¨"  # ¨
        description_addition = []
        title_postfix = []

        description = ""
        title = ""

        if self.isDrmProtected:
            title_postfix.append(drm_lock)
            description_addition.append(
                LanguageHelper.get_localized_string(
                    LanguageHelper.DrmProtected))

        if self.isGeoLocked:
            title_postfix.append(geo_lock)
            description_addition.append(
                LanguageHelper.get_localized_string(
                    LanguageHelper.GeoLockedId))

        if self.isPaid:
            title_postfix.append(paid)
            description_addition.append(
                LanguageHelper.get_localized_string(
                    LanguageHelper.PremiumPaid))

        if self.isCloaked:
            title_postfix.append(cloaked)
            description_addition.append(
                LanguageHelper.get_localized_string(LanguageHelper.HiddenItem))

        # actually update it
        if description_addition:
            description_addition = ", ".join(description_addition)
            description = "\n\n[COLOR gold][I]%s[/I][/COLOR]" % (
                description_addition, )
        if title_postfix:
            title = " [COLOR gold]%s[/COLOR]" % ("".join(title_postfix), )

        return title, description
Exemple #6
0
    def list_dates(self, data):
        """ Generates a list of the past week days.

        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 = []

        # https://api.kijk.nl/v2/templates/page/missed/all/20180201
        days = [
            "Maandag", "Dinsdag", "Woensdag", "Donderdag", "Vrijdag",
            "Zaterdag", "Zondag"
        ]
        for i in range(0, 7):
            date = datetime.datetime.now() - datetime.timedelta(days=i)
            # https://api.kijk.nl/v2/templates/page/missed/all/20180626
            # url = "https://api.kijk.nl/v2/templates/page/missed/all/{0}{1:02d}{2:02d}".format(date.year, date.month, date.day)
            # https://api.kijk.nl/v1/default/sections/missed-all-20180619
            url = "https://api.kijk.nl/v1/default/sections/missed-all-{0}{1:02d}{2:02d}".format(
                date.year, date.month, date.day)
            if i == 0:
                title = LanguageHelper.get_localized_string(
                    LanguageHelper.Today)
            elif i == 1:
                title = LanguageHelper.get_localized_string(
                    LanguageHelper.Yesterday)
            elif i == 2:
                title = LanguageHelper.get_localized_string(
                    LanguageHelper.DayBeforeYesterday)
            else:
                day_name = days[date.weekday()]
                title = day_name

            date_item = MediaItem(title, url)
            date_item.set_date(date.year, date.month, date.day)
            items.append(date_item)

        Logger.debug("Pre-Processing finished")
        return data, items
Exemple #7
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
    def create_json_page_item(self, result_set):
        """ Creates a MediaItem of type 'page' 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[str,str] result_set: The result_set of the self.episodeItemRegex

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

        """

        Logger.trace(result_set)

        if "nextPageUrl" not in result_set:
            return None

        title = "\b.: %s :." % (LanguageHelper.get_localized_string(
            LanguageHelper.MorePages), )
        url = "%s%s" % (self.baseUrl, result_set["nextPageUrl"])
        item = MediaItem(title, url)
        item.icon = self.icon
        item.thumb = self.noImage
        item.complete = True
        return item
Exemple #9
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
    def add_live_channel(self, data):
        """ Performs pre-process actions for data processing.

        Accepts an data from the process_folder_list method, BEFORE the items are
        processed. Allows setting of parameters (like title etc) for the channel.
        Inside this method the <data> could be changed and additional items can
        be created.

        The return values should always be instantiated in at least ("", []).

        :param str data: The retrieve data that was loaded for the current item and URL.

        :return: A tuple of the data and a list of MediaItems that were generated.
        :rtype: tuple[str|JsonHelper,list[MediaItem]]

        """

        Logger.info("Performing Pre-Processing")
        items = []

        title = LanguageHelper.get_localized_string(
            LanguageHelper.LiveStreamTitleId)
        item = MediaItem("\a.: {} :.".format(title), "")
        item.type = "folder"
        items.append(item)

        live_item = MediaItem(title, "#livestream")
        live_item.type = "video"
        live_item.isLive = True
        item.items.append(live_item)

        Logger.debug("Pre-Processing finished")
        return data, items
    def create_alpha_item(self, result_set):
        """ Creates a MediaItem of type 'folder' using the Alpha chars available. It uses
        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

        """

        program_count = result_set.get("availableInternationally", 0)
        if program_count <= 0:
            return None

        title = result_set["title"]
        url_part = title.lower()
        if url_part == "0-9":
            url_part = "$"
        url = "https://psapi.nrk.no/medium/tv/letters/{}/indexelements?onlyOnDemandRights=false&" \
              "apiKey={}".format(url_part, self.__api_key)

        title = LanguageHelper.get_localized_string(
            LanguageHelper.StartWith) % (title, )
        item = MediaItem(title, url)
        item.icon = self.icon
        item.type = 'folder'
        item.fanart = self.fanart
        item.thumb = self.noImage
        return item
    def create_page_item(self, result_set):
        """ Creates a MediaItem of type 'page' 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[str,str] result_set: The result_set of the self.episodeItemRegex

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

        """

        Logger.trace(result_set)
        next_page = result_set["next"]
        if not next_page:
            Logger.debug("No more items available")
            return None

        more = LanguageHelper.get_localized_string(LanguageHelper.MorePages)
        url = "%s=%s" % (self.parentItem.url.rsplit("=", 1)[0], next_page)
        item = MediaItem(more, url)
        item.thumb = self.parentItem.thumb
        item.icon = self.icon
        item.fanart = self.parentItem.fanart
        item.complete = True
        return item
Exemple #13
0
    def __get_title(self, name):
        """ Create the title based on the MediaItems name and type.

        :param str name: the name to update.

        :return: an updated name
        :rtype: str

        """

        if not name:
            name = self.name

        if self.type == 'page':
            # We need to add the Page prefix to the item
            name = "%s %s" % (LanguageHelper.get_localized_string(
                LanguageHelper.Page), name)
            Logger.debug("MediaItem.__get_title :: Adding Page Prefix")

        elif self.__date != '' and not self.is_playable():
            # not playable items should always show date
            name = "%s [COLOR=dimgray](%s)[/COLOR]" % (name, self.__date)

        folder_prefix = AddonSettings.get_folder_prefix()
        if self.type == "folder" and not folder_prefix == "":
            name = "%s %s" % (folder_prefix, name)

        return name
Exemple #14
0
    def add_live_channel_and_extract_data(self, data):
        """ Add the live channel and extract the correct data to process further.

        The return values should always be instantiated in at least ("", []).

        :param str data: The retrieve data that was loaded for the current item and URL.

        :return: A tuple of the data and a list of MediaItems that were generated.
        :rtype: tuple[str|JsonHelper,list[MediaItem]]

        """
        Logger.info("Performing Pre-Processing")
        items = []

        title = LanguageHelper.get_localized_string(LanguageHelper.LiveStreamTitleId)
        item = MediaItem("\a.: {} :.".format(title), self.liveUrl)
        item.type = "folder"
        items.append(item)

        if not data:
            return "[]", items

        json_data = Regexer.do_regex(r"setupBroadcastArchive\('Tv',\s*([^;]+)\);", data)
        if isinstance(json_data, (tuple, list)) and len(json_data) > 0:
            Logger.debug("Pre-Processing finished")
            return json_data[0], items

        Logger.info("Cannot extract JSON data from HTML.")
        return data, items
    def alpha_listing(self, data):
        """ Creates a alpha listing with items pointing to the alpha listing on line.

        :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 an Alpha list for BBC")

        items = []
        # https://www.bbc.co.uk/iplayer/a-z/a

        title_format = LanguageHelper.get_localized_string(
            LanguageHelper.StartWith)
        url_format = "https://www.bbc.co.uk/iplayer/a-z/%s"
        for char in "abcdefghijklmnopqrstuvwxyz0":
            if char == "0":
                char = "0-9"
            sub_item = MediaItem(title_format % (char.upper(), ),
                                 url_format % (char, ))
            sub_item.complete = True
            sub_item.icon = self.icon
            sub_item.thumb = self.noImage
            sub_item.dontGroup = True
            sub_item.HttpHeaders = {"X-Requested-With": "XMLHttpRequest"}
            items.append(sub_item)
        return data, items
Exemple #16
0
    def set_bitrate(self):
        """ Sets the bitrate for the selected channel via a specific dialog. """

        if self.channelObject is None:
            raise ValueError("Missing channel")

        # taken from the settings.xml
        bitrate_options = "Retrospect|100|250|500|750|1000|1500|2000|2500|4000|8000|20000"\
            .split("|")

        current_bitrate = AddonSettings.get_max_channel_bitrate(
            self.channelObject)
        Logger.debug("Found bitrate for %s: %s", self.channelObject,
                     current_bitrate)
        current_bitrate_index = 0 if current_bitrate not in bitrate_options \
            else bitrate_options.index(current_bitrate)

        dialog = xbmcgui.Dialog()
        heading = LanguageHelper.get_localized_string(
            LanguageHelper.BitrateSelection)
        selected_bitrate = dialog.select(heading,
                                         bitrate_options,
                                         preselect=current_bitrate_index)
        if selected_bitrate < 0:
            return

        Logger.info("Changing bitrate for %s from %s to %s",
                    self.channelObject, bitrate_options[current_bitrate_index],
                    bitrate_options[selected_bitrate])

        AddonSettings.set_max_channel_bitrate(
            self.channelObject, bitrate_options[selected_bitrate])
        return
    def add_live_streams(self, data):
        """ Performs pre-process actions for data processing.

        Accepts an data from the process_folder_list method, BEFORE the items are
        processed. Allows setting of parameters (like title etc) for the channel.
        Inside this method the <data> could be changed and additional items can
        be created.

        The return values should always be instantiated in at least ("", []).

        :param str data: The retrieve data that was loaded for the current item and URL.

        :return: A tuple of the data and a list of MediaItems that were generated.
        :rtype: tuple[str|JsonHelper,list[MediaItem]]

        """

        items = []
        if self.parentItem is None:
            live_item = MediaItem(
                "\a.: Live TV :.",
                "https://d5ms27yy6exnf.cloudfront.net/live/omroepflevoland/tv/index.m3u8"
            )
            live_item.icon = self.icon
            live_item.thumb = self.noImage
            live_item.type = 'video'
            live_item.dontGroup = True
            now = datetime.datetime.now()
            live_item.set_date(now.year, now.month, now.day, now.hour,
                               now.minute, now.second)
            items.append(live_item)

            live_item = MediaItem(
                "\a.: Live Radio :.",
                "https://d5ms27yy6exnf.cloudfront.net/live/omroepflevoland/radio/index.m3u8"
            )
            live_item.icon = self.icon
            live_item.thumb = self.noImage
            live_item.type = 'video'
            live_item.dontGroup = True
            now = datetime.datetime.now()
            live_item.set_date(now.year, now.month, now.day, now.hour,
                               now.minute, now.second)
            items.append(live_item)

        # add "More"
        more = LanguageHelper.get_localized_string(LanguageHelper.MorePages)
        current_url = self.parentItem.url if self.parentItem is not None else self.mainListUri
        url, page = current_url.rsplit("=", 1)
        url = "{}={}".format(url, int(page) + 1)

        item = MediaItem(more, url)
        item.thumb = self.noImage
        item.icon = self.icon
        item.fanart = self.fanart
        item.complete = True
        items.append(item)

        return data, items
    def create_main_list(self, data):
        """ Performs pre-process actions for data processing and creates the main menu list

        Accepts an data from the process_folder_list method, BEFORE the items are
        processed. Allows setting of parameters (like title etc) for the channel.
        Inside this method the <data> could be changed and additional items can
        be created.

        The return values should always be instantiated in at least ("", []).

        :param str data: The retrieve data that was loaded for the current item and URL.

        :return: A tuple of the data and a list of MediaItems that were generated.
        :rtype: tuple[str|JsonHelper,list[MediaItem]]

        """

        Logger.info("Performing Pre-Processing")
        items = []

        live = LanguageHelper.get_localized_string(
            LanguageHelper.LiveStreamTitleId)
        live_tv = "{} - TV".format(live)
        live_radio = "{} - Radio".format(live)

        links = {
            live_tv:
            "https://psapi.nrk.no/tv/live?apiKey={}".format(self.__api_key),
            live_radio:
            "https://psapi.nrk.no/radio/live?apiKey={}".format(self.__api_key),
            "Recommended":
            "https://psapi.nrk.no/medium/tv/recommendedprograms?maxnumber=100&startRow=0&apiKey={}"
            .format(self.__api_key),
            "Popular":
            "https://psapi.nrk.no/medium/tv/popularprogramssuper?maxnumber=100&startRow=0&apiKey={}"
            .format(self.__api_key),
            "Recent":
            "https://psapi.nrk.no/medium/tv/recentlysentprograms?maxnumber=100&startRow=0&apiKey={}"
            .format(self.__api_key),
            "Categories":
            "https://psapi.nrk.no/medium/tv/categories?apiKey={}".format(
                self.__api_key),
            "A - Å":
            "https://psapi.nrk.no/medium/tv/letters?apiKey={}".format(
                self.__api_key),
            "S&oslash;k":
            "#searchSite"
        }
        for name, url in links.items():
            item = MediaItem(name, url)
            item.icon = self.icon
            item.thumb = self.noImage
            item.complete = True
            item.HttpHeaders = self.httpHeaders
            items.append(item)

        Logger.debug("Pre-Processing finished")
        return data, items
    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
Exemple #20
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)
    def reset():
        """ Resets the Vault and Retrospect Machine key, making all encrypted values
        useless.

        :rtype: None

        """

        ok = XbmcWrapper.show_yes_no(LanguageHelper.get_localized_string(LanguageHelper.VaultReset),
                                     LanguageHelper.get_localized_string(LanguageHelper.VaultResetConfirm))
        if not ok:
            Logger.debug("Aborting Reset Vault")
            return

        Logger.info("Resetting the vault to a new initial state.")
        AddonSettings.set_setting(Vault.__APPLICATION_KEY_SETTING, "", store=LOCAL)

        # create a vault instance so we initialize a new one with a new PIN.
        Vault()
        return
Exemple #22
0
    def set_inputstream_adaptive(self):
        """ Set the InputStream Adaptive for this channel """

        if self.channelObject is None:
            raise ValueError("Missing channel")

        if not self.channelObject.adaptiveAddonSelectable:
            Logger.warning(
                "Cannot set InputStream Adaptive add-on mode for %s",
                self.channelObject)
            return

        current_mode = AddonSettings.get_adaptive_mode(self.channelObject)
        mode_values = [None, True, False]
        current_index = mode_values.index(current_mode)
        mode_options = [
            LanguageHelper.get_localized_string(LanguageHelper.Retrospect),
            LanguageHelper.get_localized_string(LanguageHelper.Enabled),
            LanguageHelper.get_localized_string(LanguageHelper.Disabled)
        ]

        dialog = xbmcgui.Dialog()
        heading = LanguageHelper.get_localized_string(
            LanguageHelper.ChannelAdaptiveMode)
        selected_index = dialog.select(heading,
                                       mode_options,
                                       preselect=current_index)
        if selected_index < 0:
            return
        selected_value = mode_values[selected_index]

        Logger.info("Changing InputStream Adaptive mode for %s from %s to %s",
                    self.channelObject, mode_options[current_index],
                    mode_options[selected_index])

        AddonSettings.set_adaptive_mode(self.channelObject, selected_value)

        # Refresh if we have a video item selected, so the cached urls are removed.
        if self.keywordPickle in self.params:
            Logger.debug("Refreshing list to clear URL caches")
            self.refresh()
Exemple #23
0
    def select_channels(self):
        """ Selects the channels that should be visible.

        @return: None
        """

        valid_channels = ChannelIndex.get_register().get_channels(
            include_disabled=True)
        channels_to_show = [c for c in valid_channels if c.visible]
        # The old way
        # channels_to_show = filter(lambda c: c.visible, valid_channels)

        selected_channels = [c for c in channels_to_show if c.enabled]
        selected_indices = list(
            [channels_to_show.index(c) for c in selected_channels])
        Logger.debug("Currently selected channels: %s", selected_indices)

        channel_to_show_names = [
            HtmlEntityHelper.convert_html_entities(c.channelName)
            for c in channels_to_show
        ]
        # The old way
        # channel_to_show_names = list(map(lambda c: HtmlEntityHelper.convert_html_entities(c.channelName), channels_to_show))

        dialog = xbmcgui.Dialog()
        heading = LanguageHelper.get_localized_string(
            LanguageHelper.ChannelSelection)[:-1]
        selected_channels = dialog.multiselect(heading,
                                               channel_to_show_names,
                                               preselect=selected_indices)
        if selected_channels is None:
            return

        selected_channels = list(selected_channels)
        Logger.debug("New selected channels:       %s", selected_channels)

        indices_to_remove = [
            i for i in selected_indices if i not in selected_channels
        ]
        indices_to_add = [
            i for i in selected_channels if i not in selected_indices
        ]
        for i in indices_to_remove:
            Logger.info("Hiding channel: %s", channels_to_show[i])
            AddonSettings.set_channel_visiblity(channels_to_show[i], False)

        for i in indices_to_add:
            Logger.info("Showing channel: %s", channels_to_show[i])
            AddonSettings.set_channel_visiblity(channels_to_show[i], True)

        self.refresh()
        return
    def create_page_item(self, result_set):
        """ Creates a MediaItem of type 'page' 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 'page'.
        :rtype: MediaItem|None

        """

        if "totalPages" not in result_set:
            return None

        Logger.debug("Starting create_page_item")

        # current page?
        page_uri_part = "page%5Bnumber%5D="
        if page_uri_part not in self.parentItem.url:
            page = 1
            url_format = "{0}&page%5Bnumber%5D={{0:d}}".format(
                self.parentItem.url)
        else:
            base_url, page_part = self.parentItem.url.rsplit(page_uri_part, 1)
            next_part = page_part.find("&")
            if next_part < 0:
                # end
                page = int(page_part)
                url_format = "{0}&page%5Bnumber%5D={{0:d}}".format(base_url)
            else:
                page = int(page_part[0:next_part])
                url_format = "{0}&page%5Bnumber%5D={{0:d}}&{1}".format(
                    base_url, page_part[next_part:])

        max_pages = result_set.get("totalPages", 0)
        Logger.trace("Current Page: %d of %d (%s)", page, max_pages,
                     self.parentItem.url)

        if page + 1 > max_pages:
            return None

        title = LanguageHelper.get_localized_string(LanguageHelper.MorePages)
        url = url_format.format(page + 1)
        item = MediaItem(title, url)
        item.fanart = self.parentItem.fanart
        item.thumb = self.parentItem.thumb
        return item
    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)
    def add_categories(self, data):
        """ Adds categories to the main listings.

        The return values should always be instantiated in at least ("", []).

        :param str data: The retrieve data that was loaded for the current item and URL.

        :return: A tuple of the data and a list of MediaItems that were generated.
        :rtype: tuple[str|JsonHelper,list[MediaItem]]

        """

        Logger.info("Performing Pre-Processing")
        items = []

        if self.parentItem and "code" in self.parentItem.metaData:
            self.__currentChannel = self.parentItem.metaData["code"]
            Logger.info("Only showing items for channel: '%s'",
                        self.__currentChannel)
            return data, items

        cat = MediaItem("\a.: Categori&euml;n :.",
                        "https://www.vrt.be/vrtnu/categorieen/")
        cat.fanart = self.fanart
        cat.thumb = self.noImage
        cat.icon = self.icon
        cat.dontGroup = True
        items.append(cat)

        live = MediaItem("\a.: Live Streams :.",
                         "https://services.vrt.be/videoplayer/r/live.json")
        live.fanart = self.fanart
        live.thumb = self.noImage
        live.icon = self.icon
        live.dontGroup = True
        live.isLive = True
        items.append(live)

        channel_text = LanguageHelper.get_localized_string(30010)
        channels = MediaItem("\a.: %s :." % (channel_text, ), "#channels")
        channels.fanart = self.fanart
        channels.thumb = self.noImage
        channels.icon = self.icon
        channels.dontGroup = True
        items.append(channels)

        Logger.debug("Pre-Processing finished")
        return data, items
    def create_folder_item(self, result_set):
        """ Creates a MediaItem of type '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.

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

        result_set["title"] = LanguageHelper.get_localized_string(LanguageHelper.MorePages)
        return chn_class.Channel.create_folder_item(self, result_set)
Exemple #28
0
    def set_setting(self,
                    setting_id,
                    setting_name=None,
                    setting_action_id=None):
        """ Reads a value for a setting from the keyboard and encryptes it in the Kodi
        Add-on settings.

        The setttingActionId defaults to <settingId>_set

        :param str setting_id:          The ID for the Kodi Add-on setting to set.
        :param str setting_name:        The name to display in the keyboard.
        :param str setting_action_id:   The name of the action that was called.

        :rtype: None

        """

        Logger.info("Encrypting value for setting '%s'", setting_id)
        input_value = XbmcWrapper.show_key_board(
            "",
            LanguageHelper.get_localized_string(
                LanguageHelper.VaultSpecifySetting) %
            (setting_name or setting_id, ))

        if input_value is None:
            Logger.debug("Setting of encrypted value cancelled.")
            return

        value = "%s=%s" % (setting_id, input_value)
        encrypted_value = self.__encrypt(value, Vault.__Key)

        if setting_action_id is None:
            setting_action_id = "%s_set" % (setting_id, )

        Logger.debug("Updating '%s' and '%s'", setting_id, setting_action_id)
        AddonSettings.set_setting(setting_id, encrypted_value)
        if input_value:
            AddonSettings.set_setting(setting_action_id, "******")
        else:
            AddonSettings.set_setting(setting_action_id, "")
        Logger.info("Successfully encrypted value for setting '%s'",
                    setting_id)
        return
    def add_page_items(self, data):
        """ Performs pre-process actions for data processing.

        Accepts an data from the process_folder_list method, BEFORE the items are
        processed. Allows setting of parameters (like title etc) for the channel.
        Inside this method the <data> could be changed and additional items can
        be created.

        The return values should always be instantiated in at least ("", []).

        :param str data: The retrieve data that was loaded for the current item and URL.

        :return: A tuple of the data and a list of MediaItems that were generated.
        :rtype: tuple[str|JsonHelper,list[MediaItem]]

        """

        Logger.info("Performing Pre-Processing")
        items = []
        json = JsonHelper(data)
        total_results = json.get_value("totalResults")
        from_value = json.get_value("from")
        size_value = json.get_value("size")

        if from_value + size_value < total_results:
            more_pages = LanguageHelper.get_localized_string(
                LanguageHelper.MorePages)
            url = self.parentItem.url.split('?')[0]
            url = "%s?size=%s&from=%s&sort=Nieuwste" % (
                url, size_value, from_value + size_value)
            Logger.debug("Adding next-page item from %s to %s",
                         from_value + size_value,
                         from_value + size_value + size_value)

            next_page = MediaItem(more_pages, url)
            next_page.icon = self.parentItem.icon
            next_page.fanart = self.parentItem.fanart
            next_page.thumb = self.parentItem.thumb
            next_page.dontGroup = True
            items.append(next_page)

        Logger.debug("Pre-Processing finished")
        return json, items
Exemple #30
0
    def get_kodi_item(self):
        """ Creates an Kodi ListItem object for this channel
        
        :return: a Kodi ListItem with all required properties set.
        :rtype: xbmcgui.ListItem

        """

        name = HtmlEntityHelper.convert_html_entities(self.channelName)
        description = HtmlEntityHelper.convert_html_entities(
            self.channelDescription)

        if self.uses_external_addon:
            other = LanguageHelper.get_localized_string(
                LanguageHelper.OtherAddon)
            name = "{0} {1} [COLOR gold]{2}[/COLOR]".format(
                name, unichr(187), other)

        self.icon = self.__get_image_path(self.icon)
        item = xbmcgui.ListItem(name, description)
        item.setArt({'thumb': self.icon, 'icon': self.icon})

        # http://mirrors.kodi.tv/docs/python-docs/14.x-helix/xbmcgui.html#ListItem-setInfo
        item.setInfo(
            "video",
            {
                "Title": name,
                # "Count": self.sortOrderPerCountry,
                # "TrackNumber": self.sortOrder,
                "Genre": LanguageHelper.get_full_language(self.language),
                # "Tagline": description,
                "Plot": description
            })

        if AddonSettings.hide_fanart():
            return item

        if self.fanart is not None:
            self.fanart = self.__get_image_path(self.fanart)
        else:
            self.fanart = os.path.join(Config.rootDir, "fanart.jpg")
        item.setArt({'fanart': self.fanart})
        return item