예제 #1
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
예제 #2
0
    def show_country_settings(self):
        """ Shows the country settings page where channels can be shown/hidden based on the
        country of origin. """

        if AddonSettings.is_min_version(18):
            AddonSettings.show_settings(-99)
        else:
            AddonSettings.show_settings(101)
        self.refresh()
예제 #3
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
예제 #4
0
    def __exit__(self, exc_type, exc_val, exc_tb):
        if exc_val:
            Logger.critical("Error in menu handling: %s",
                            exc_val.message,
                            exc_info=True)

        # make sure we leave no references behind
        AddonSettings.clear_cached_addon_settings_object()
        # close the log to prevent locking on next call
        Logger.instance().close_log()
        return False
예제 #5
0
    def __configure_channel(self, channel_info):
        """ Shows the current channels settings dialog.

        :param ChannelInfo channel_info:    The channel info for the channel

        """

        if not channel_info:
            Logger.warning("Cannot configure channel without channel info")

        Logger.info("Configuring channel: %s", channel_info)
        AddonSettings.show_channel_settings(channel_info)
예제 #6
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()
예제 #7
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
예제 #8
0
    def GetDefaultCachePath(self):
        """ returns the default cache path for this channel"""

        # set the UZG path
        if AddonSettings.GetUzgCacheDuration() > 0:
            cachPath = AddonSettings.GetUzgCachePath()
            if cachPath:
                Logger.Trace("UZG Cache path resolved to: %s", cachPath)
                return cachPath

        cachePath = chn_class.Channel.GetDefaultCachePath(self)
        Logger.Trace("UZG Cache path resolved chn_class default: %s", cachePath)
        return cachePath
예제 #9
0
    def __ShowFirstTimeMessage(self, channelInfo):
        # type: (ChannelInfo) -> None
        """ Checks if it is the first time a channel is executed
        and if a first time message is available it will be shown

        Arguments:
        channelName : string - Name of the channelfile that is loaded
        channelPath : string - Path of the channelfile

        Shows a message dialog if the message should be shown.

        Make sure that each line fits in a single line of a XBMC Dialog box (50 chars)

        """

        hideFirstTime = AddonSettings.HideFirstTimeMessages()
        if channelInfo.firstTimeMessage:
            if not hideFirstTime:
                Logger.Info("Showing first time message '%s' for channel chn_%s.",
                            channelInfo.firstTimeMessage, channelInfo.moduleName)

                title = LanguageHelper.GetLocalizedString(LanguageHelper.ChannelMessageId)
                XbmcWrapper.ShowDialog(title, channelInfo.firstTimeMessage.split("|"))
            else:
                Logger.Debug("Not showing first time message due to add-on setting set to '%s'.",
                             hideFirstTime)
        return
예제 #10
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()
예제 #11
0
    def get_verifiable_video_url(self, url):
        """ Creates an RTMP(E) url that can be verified using an SWF URL.

        Returns a new URL that includes the self.swfUrl in the form of "url --swfVfy|-W swfUrl".
        If self.swfUrl == "", the original URL is returned.

        :param str url: The URL that should be made verifiable.

        :return:    A new URL that includes the self.swfUrl
        :rtype: str

        """

        if self.swfUrl == "":
            return url

        # TODO: Kodi 17.x also accepts an SWF-url as swfvfy option (https://www.ffmpeg.org/ffmpeg-protocols.html#rtmp).
        # This option should be set via the XbmcListItem.setProperty, so within Retrospect via:
        #   part.add_property("swfvfy", self.swfUrl)
        # Or as an URL parameter swfvfy where we add the full URL instead of just 1:
        #   return "%s swfvfy=%s" % (url, self.swfUrl)

        if AddonSettings.is_min_version(17):
            Logger.debug("Using Kodi 17+ RTMP parameters")
            return "%s swfvfy=%s" % (url, self.swfUrl)
        else:
            Logger.debug("Using Legacy (Kodi 16 and older) RTMP parameters")
            return "%s swfurl=%s swfvfy=1" % (url, self.swfUrl)
예제 #12
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
예제 #13
0
    def update_live_item(self, item):
        """ Updates an existing live 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

        """

        part = item.create_new_empty_media_part()
        if AddonSettings.use_adaptive_stream_add_on():
            stream = part.append_media_stream(item.url, 0)
            M3u8.set_input_stream_addon_input(stream, self.proxy)
            item.complete = True
        else:
            for s, b in M3u8.get_streams_from_m3u8(item.url, self.proxy):
                item.complete = True
                part.append_media_stream(s, b)
        return item
예제 #14
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
예제 #15
0
    def ShowCategories(self):
        """Displays the ShowCategories that are currently available in XOT as a directory
        listing.
        """

        Logger.Info("Plugin::ShowCategories")
        channelRegister = ChannelImporter.GetRegister()
        categories = channelRegister.GetCategories()

        xbmcItems = []
        icon = os.path.join(Config.rootDir, "icon.png")
        fanart = os.path.join(Config.rootDir, "fanart.jpg")
        for category in categories:
            name = LanguageHelper.GetLocalizedCategory(category)
            xbmcItem = xbmcgui.ListItem(name, name)

            # set art
            try:
                xbmcItem.setIconImage(icon)
            except:
                # it was deprecated
                pass
            xbmcItem.setArt({'thumb': icon, 'icon': icon})
            if not AddonSettings.HideFanart():
                xbmcItem.setArt({'fanart': fanart})

            url = self.__CreateActionUrl(None, action=self.actionListCategory, category=category)
            xbmcItems.append((url, xbmcItem, True))

        Logger.Trace(xbmcItems)
        ok = xbmcplugin.addDirectoryItems(self.handle, xbmcItems, len(xbmcItems))
        xbmcplugin.addSortMethod(handle=self.handle, sortMethod=xbmcplugin.SORT_METHOD_LABEL)
        xbmcplugin.endOfDirectory(self.handle, ok)
        return ok
예제 #16
0
    def GetXBMCItem(self):
        """ Creates an Xbmc ListItem object for this channel """

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

        self.icon = self.__GetImagePath(self.icon)
        item = xbmcgui.ListItem(name, description)
        try:
            item.setIconImage(self.icon)
        except:
            # it was deprecated
            pass
        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.GetFullLanguage(self.language),
                               # "Tagline": description,
                               "Plot": description})

        if AddonSettings.HideFanart():
            return item

        if self.fanart is not None:
            self.fanart = self.__GetImagePath(self.fanart)
        else:
            self.fanart = os.path.join(Config.rootDir, "fanart.jpg")
        item.setArt({'fanart': self.fanart})
        return item
예제 #17
0
    def AddLiveChannel(self, data):
        Logger.Info("Performing Pre-Processing")
        # if self.channelCode != "vtm":
        #     return data, []

        username = AddonSettings.GetSetting("mediaan_username")
        if not username:
            return data, []

        items = []

        if self.channelCode == "vtm":
            item = MediaItem("Live VTM", "#livestream")
        else:
            item = MediaItem("Live Q2", "#livestream")
        item.type = "video"
        item.isLive = True
        item.fanart = self.fanart
        item.thumb = self.noImage
        now = datetime.datetime.now()
        item.SetDate(now.year, now.month, now.day, now.hour, now.minute, now.second)
        items.append(item)

        if self.channelCode == "vtm":
            recent = MediaItem("\a.: Recent :.", "https://vtm.be/video/volledige-afleveringen/id")
            item.fanart = self.fanart
            item.thumb = self.noImage
            item.dontGroup = True
            items.append(recent)

        Logger.Debug("Pre-Processing finished")
        return data, items
예제 #18
0
    def get_setting(self, setting_id):
        """ Retrieves an encrypted setting from the Kodi Add-on Settings.

        :param str setting_id: the ID for the setting to retrieve.

        :return: the decrypted value for the setting.
        :rtype: str
        """

        Logger.info("Decrypting value for setting '%s'", setting_id)
        encrypted_value = AddonSettings.get_setting(setting_id)
        if not encrypted_value:
            return encrypted_value

        try:
            decrypted_value = self.__decrypt(encrypted_value, Vault.__Key)
            if not decrypted_value.startswith(setting_id):
                Logger.error("Invalid decrypted value for setting '%s'",
                             setting_id)
                return None

            decrypted_value = decrypted_value[len(setting_id) + 1:]
            Logger.info("Successfully decrypted value for setting '%s'",
                        setting_id)
        except UnicodeDecodeError:
            Logger.error(
                "Invalid Unicode data returned from decryption. Must be wrong data"
            )
            return None

        return decrypted_value
예제 #19
0
    def GetSetting(self, settingId):
        """ Retrieves an encrypted setting from the Kodi Add-on Settings.

        @param settingId: the ID for the setting to retrieve
        @return:          the decrypted value for the setting
        """

        Logger.Info("Decrypting value for setting '%s'", settingId)
        encryptedValue = AddonSettings.GetSetting(settingId)
        if not encryptedValue:
            return encryptedValue

        try:
            decryptedValue = self.__Decrypt(encryptedValue, Vault.__Key)
            if not decryptedValue.startswith(settingId):
                Logger.Error("Invalid decrypted value for setting '%s'", settingId)
                return None

            decryptedValue = decryptedValue[len(settingId) + 1:]
            Logger.Info("Successfully decrypted value for setting '%s'", settingId)
        except UnicodeDecodeError:
            Logger.Error("Invalid Unicode data returned from decryption. Must be wrong data")
            return None

        return decryptedValue
예제 #20
0
    def __GetApplicationKey(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
        """

        applicationKeyEncrypted = AddonSettings.GetSetting(Vault.__APPLICATION_KEY_SETTING)
        if not applicationKeyEncrypted:
            return None

        vaultIncorrectPin = LanguageHelper.GetLocalizedString(LanguageHelper.VaultIncorrectPin)
        pin = XbmcWrapper.ShowKeyBoard(
            heading=LanguageHelper.GetLocalizedString(LanguageHelper.VaultInputPin),
            hidden=True)
        if not pin:
            XbmcWrapper.ShowNotification("", vaultIncorrectPin, XbmcWrapper.Error)
            raise RuntimeError("Incorrect Retrospect PIN specified")
        pinKey = self.__GetPBK(pin)
        applicationKey = self.__Decrypt(applicationKeyEncrypted, pinKey)
        if not applicationKey.startswith(Vault.__APPLICATION_KEY_SETTING):
            Logger.Critical("Invalid Retrospect PIN")
            XbmcWrapper.ShowNotification("", vaultIncorrectPin, XbmcWrapper.Error)
            raise RuntimeError("Incorrect Retrospect PIN specified")

        applicationKeyValue = applicationKey[len(Vault.__APPLICATION_KEY_SETTING) + 1:]
        Logger.Info("Successfully decrypted the ApplicationKey.")
        return applicationKeyValue
예제 #21
0
    def __GetTitle(self, name):
        """ Create the title based on the MediaItems name and type.

        @param name: (string) the name to update
        @return:     (string) an updated name

        """

        if not name:
            name = self.name

        if self.type == 'page':
            # We need to add the Page prefix to the item
            name = "Page %s" % (name, )
            Logger.Debug("GetXBMCItem :: Adding Page Prefix")

        elif self.__date != '' and not self.IsPlayable():
            # not playable items should always show date
            name = "%s (%s)" % (name, self.__date)

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

        return name
예제 #22
0
    def update_json_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

        """

        headers = {}
        if self.localIP:
            headers.update(self.localIP)

        data = UriHandler.open(item.url,
                               proxy=self.proxy,
                               additional_headers=headers)
        video_data = JsonHelper(data)
        stream_data = video_data.get_value("mediaAssetsOnDemand")
        if not stream_data:
            return item

        use_adaptive = AddonSettings.use_adaptive_stream_add_on()
        stream_data = stream_data[0]
        part = item.create_new_empty_media_part()
        if "hlsUrl" in stream_data:
            hls_url = stream_data["hlsUrl"]
            if use_adaptive:
                stream = part.append_media_stream(hls_url, 0)
                M3u8.set_input_stream_addon_input(stream,
                                                  self.proxy,
                                                  headers=headers)
                item.complete = True
            else:
                for s, b in M3u8.get_streams_from_m3u8(hls_url,
                                                       self.proxy,
                                                       headers=headers):
                    item.complete = True
                    part.append_media_stream(s, b)

        if "timedTextSubtitlesUrl" in stream_data and stream_data[
                "timedTextSubtitlesUrl"]:
            sub_url = stream_data["timedTextSubtitlesUrl"].replace(
                ".ttml", ".vtt")
            sub_url = HtmlEntityHelper.url_decode(sub_url)
            part.Subtitle = SubtitleHelper.download_subtitle(sub_url,
                                                             format="webvtt")
        return item
예제 #23
0
    def __IsNewVersionAvailable(self):
        """ Verifies that there is a new version available. It compares the addons.xml.md5 with the stored one.

        @return: True or False
        """

        # first check if there is a "channel" folder
        channelPath = os.path.join(Config.rootDir, "channels")
        if not os.path.isdir(channelPath):
            Logger.Warning(
                "No Channels found at '%s', skipping updates for now.",
                channelPath)
            return False

        onlineData = UriHandler.Open(Config.UpdateUrl)
        self.__NewMd5 = onlineData.strip()
        self.__OldMd5 = AddonSettings.GetCurrentAddonXmlMd5()

        updated = self.__OldMd5 != self.__NewMd5
        if updated:
            Logger.Info("New updates are available ('%s' vs '%s')",
                        self.__OldMd5, self.__NewMd5)
        else:
            Logger.Info("No new updates available, MD5 hashes match")
        return updated
예제 #24
0
    def LogOn(self):
        signatureSettings = "mediaan_signature"
        signatureSetting = AddonSettings.GetSetting(signatureSettings)
        # apiKey = "3_HZ0FtkMW_gOyKlqQzW5_0FHRC7Nd5XpXJZcDdXY4pk5eES2ZWmejRW5egwVm4ug-"  # from VTM
        apiKey = "3_OEz9nzakKMkhPdUnz41EqSRfhJg5z9JXvS4wUORkqNf2M2c1wS81ilBgCewkot97"  # from Stievie
        if signatureSetting and "|" not in signatureSetting:
            url = "https://accounts.eu1.gigya.com/accounts.getAccountInfo"
            data = "APIKey=%s" \
                   "&sdk=js_7.4.30" \
                   "&login_token=%s" % (apiKey, signatureSetting, )
            logonData = UriHandler.Open(url,
                                        params=data,
                                        proxy=self.proxy,
                                        noCache=True)
            if self.__ExtractSessionData(logonData, signatureSettings):
                return True
            Logger.Warning("Failed to extend the VTM.be session.")

        Logger.Info("Logging onto VTM.be")
        v = Vault()
        password = v.GetSetting("mediaan_password")
        username = AddonSettings.GetSetting("mediaan_username")
        if not username or not password:
            XbmcWrapper.ShowDialog(
                title=None,
                lines=LanguageHelper.GetLocalizedString(
                    LanguageHelper.MissingCredentials),
                # notificationType=XbmcWrapper.Error,
                # displayTime=5000
            )
            return False

        Logger.Debug("Using: %s / %s", username, "*" * len(password))
        url = "https://accounts.eu1.gigya.com/accounts.login"
        data = "loginID=%s" \
               "&password=%s" \
               "&targetEnv=jssdk" \
               "&APIKey=%s" \
               "&includeSSOToken=true" \
               "&authMode=cookie" % \
               (HtmlEntityHelper.UrlEncode(username), HtmlEntityHelper.UrlEncode(password), apiKey)

        logonData = UriHandler.Open(url,
                                    params=data,
                                    proxy=self.proxy,
                                    noCache=True)
        return self.__ExtractSessionData(logonData, signatureSettings)
예제 #25
0
    def __set_proxy(self, language, proxy_id, local_ip):
        """ Sets the proxy and local IP configuration for channels.

        :param str language:    The language for what channels to update.
        :param int proxy_id:    The proxy index to use.
        :param int local_ip:    The local_ip index to use.
        
        If no proxy_id is specified (None) then the proxy_id will be determined based on language
        If no local_ip is specified (None) then the local_ip will be determined based on language
        
        """

        languages = AddonSettings.get_available_countries(
            as_country_codes=True)

        if language is not None and language not in languages:
            Logger.warning("Missing language: %s", language)
            return

        if proxy_id is None:
            proxy_id = languages.index(language)
        else:
            # noinspection PyTypeChecker
            proxy_id = int(proxy_id)

        if local_ip is None:
            local_ip = languages.index(language)
        else:
            # noinspection PyTypeChecker
            local_ip = int(local_ip)

        channels = ChannelIndex.get_register().get_channels()
        Logger.info(
            "Setting proxy='%s' (%s) and local_ip='%s' (%s) for country '%s'",
            proxy_id, languages[proxy_id], local_ip, languages[local_ip],
            language)

        channels_in_country = [
            c for c in channels if c.language == language or language is None
        ]
        for channel in channels_in_country:
            Logger.debug("Setting Proxy for: %s", channel)
            AddonSettings.set_proxy_id_for_channel(channel, proxy_id)
            if channel.localIPSupported:
                Logger.debug("Setting Local IP for: %s", channel)
                AddonSettings.set_local_ip_for_channel(channel, local_ip)
예제 #26
0
    def DownloadVideoItem(self, item):
        """Downloads an existing MediaItem with more data.

        Arguments:
        item : MediaItem - the MediaItem that should be downloaded.

        Returns:
        The original item with more data added to it's properties.

        Used to download an <item>. If the item is not complete, the self.UpdateVideoItem
        method is called to update the item. The method downloads only the MediaStream
        with the bitrate that was set in the addon settings.

        After downloading the self.downloaded property is set.

        """

        if not item.IsPlayable():
            Logger.Error("Cannot download a folder item.")
            return item

        if item.IsPlayable():
            if not item.complete:
                Logger.Info("Fetching MediaUrl for PlayableItem[%s]", item.type)
                item = self.ProcessVideoItem(item)

            if not item.complete or not item.HasMediaItemParts():
                Logger.Error("Cannot download incomplete item or item without MediaItemParts")
                return item

            i = 1
            bitrate = AddonSettings.GetMaxStreamBitrate()
            for mediaItemPart in item.MediaItemParts:
                Logger.Info("Trying to download %s", mediaItemPart)
                stream = mediaItemPart.GetMediaStreamForBitrate(bitrate)
                downloadUrl = stream.Url
                extension = UriHandler.GetExtensionFromUrl(downloadUrl)
                if len(item.MediaItemParts) > 1:
                    saveFileName = "%s-Part_%s.%s" % (item.name, i, extension)
                else:
                    saveFileName = "%s.%s" % (item.name, extension)
                Logger.Debug(saveFileName)

                # headers = item.HttpHeaders + mediaItemPart.HttpHeaders
                headers = item.HttpHeaders.copy()
                headers.update(mediaItemPart.HttpHeaders)

                progressDialog = XbmcDialogProgressWrapper("Downloading Item", item.name, stream.Url)
                folderName = XbmcWrapper.ShowFolderSelection('Select download destination for "%s"' % (saveFileName, ))
                UriHandler.Download(downloadUrl, saveFileName, folderName, progressDialog, proxy=self.proxy,
                                    additionalHeaders=headers)
                i += 1

            item.downloaded = True

        return item
예제 #27
0
    def _GetSetting(self, settingId, valueForNone=None):
        """ Retrieves channel specific settings. Just to prevent us from importing AddonSettings in all channels.

        @param settingId: the channels specific setting
        @return: the settings value from the Add-on using the Kodi settings API

        """

        setting = AddonSettings.GetChannelSetting(self.guid, settingId, valueForNone)
        return setting
예제 #28
0
    def ChangePin(self, applicationKey=None):
        # type: (str) -> bool
        """ Stores an existing ApplicationKey using a new PIN

        @param applicationKey: an existing ApplicationKey that will be stored. If none specified,
                               the existing ApplicationKey of the Vault will be used.
        @return: indication of success
        """

        Logger.Info("Updating the ApplicationKey with a new PIN")

        if self.__newKeyGeneratedInConstructor:
            Logger.Info("A key was just generated, no need to change PINs.")
            return True

        if applicationKey is None:
            Logger.Debug("Using the ApplicationKey from the vault.")
            applicationKey = Vault.__Key
        else:
            Logger.Debug("Using the ApplicationKey from the input parameter.")

        if not applicationKey:
            raise ValueError("No ApplicationKey specified.")

        # Now we get a new PIN and (re)encrypt

        pin = XbmcWrapper.ShowKeyBoard(
            heading=LanguageHelper.GetLocalizedString(LanguageHelper.VaultNewPin),
            hidden=True)
        if not pin:
            XbmcWrapper.ShowNotification(
                "", LanguageHelper.GetLocalizedString(LanguageHelper.VaultNoPin),
                XbmcWrapper.Error)
            return False

        pin2 = XbmcWrapper.ShowKeyBoard(
            heading=LanguageHelper.GetLocalizedString(LanguageHelper.VaultRepeatPin),
            hidden=True)
        if pin != pin2:
            Logger.Critical("Mismatch in PINs")
            XbmcWrapper.ShowNotification(
                "",
                LanguageHelper.GetLocalizedString(LanguageHelper.VaultPinsDontMatch),
                XbmcWrapper.Error)
            return False

        encryptedKey = "%s=%s" % (self.__APPLICATION_KEY_SETTING, applicationKey)

        # let's generate a pin using the scrypt password-based key derivation
        pinKey = self.__GetPBK(pin)
        encryptedKey = self.__Encrypt(encryptedKey, pinKey)
        AddonSettings.SetSetting(Vault.__APPLICATION_KEY_SETTING, encryptedKey)
        Logger.Info("Successfully updated the Retrospect PIN")
        return True
예제 #29
0
 def __GetPBK(self, pin):
     salt = AddonSettings.GetClientId()
     pbk = pyscrypt.hash(password=pin,
                         salt=salt,
                         N=2 ** 7,  # should be so that Raspberry Pi can handle it
                         # N=1024,
                         r=1,
                         p=1,
                         dkLen=32)
     Logger.Trace("Generated PBK with MD5: %s", hashlib.md5(pbk).hexdigest())
     return pbk
예제 #30
0
    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