def __FetchTextures(self): texturesToRetrieve = TextureHandler.Instance().NumberOfMissingTextures() if texturesToRetrieve > 0: w = None try: # show a blocking or background progress bar if texturesToRetrieve > 4: w = XbmcDialogProgressWrapper( "%s: %s" % (Config.appName, LanguageHelper.GetLocalizedString(LanguageHelper.InitChannelTitle)), LanguageHelper.GetLocalizedString(LanguageHelper.FetchTexturesTitle), # Config.TextureUrl ) else: w = XbmcDialogProgressBgWrapper( "%s: %s" % (Config.appName, LanguageHelper.GetLocalizedString(LanguageHelper.FetchTexturesTitle)), Config.TextureUrl ) bytesTransfered = TextureHandler.Instance().FetchTextures(w.ProgressUpdate) if bytesTransfered > 0: Statistics.RegisterCdnBytes(bytesTransfered) except: Logger.Error("Error fetching textures", exc_info=True) finally: if w is not None: # always close the progress bar w.Close() return
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
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
def ShowFavourites(self, channel, replaceExisting=False): """ Show the favourites Arguments: channel : Channel - The channel to show favourites for. Might be None to show all. Keyword Arguments: replaceExisting : boolean - if True it will replace the current list """ Logger.Debug("Plugin::ShowFavourites") if channel is None: Logger.Info("Showing all favourites") else: Logger.Info("Showing favourites for: %s", channel) stopWatch = stopwatch.StopWatch("Plugin Favourites timer", Logger.Instance()) try: ok = True f = Favourites(Config.favouriteDir) favs = f.List(channel) # get (actionUrl, pickle) tuples # favs = map(lambda (a, p): (a, Pickler.DePickleMediaItem(p)), favs) if len(favs) == 0: ok = self.__ShowEmptyInformation(favs, favs=True) stopWatch.Lap("Items retrieved") # create the XBMC items xbmcItems = map(lambda item: self.__ConvertMainlistItemToXbmcItem(channel, item[1], True, item[0]), favs) stopWatch.Lap("%s items for Kodi generated" % (len(xbmcItems),)) # add them to XBMC ok = ok and xbmcplugin.addDirectoryItems(self.handle, xbmcItems, len(xbmcItems)) # add sort handle, but don't use any dates as they make no sense for favourites self.__AddSortMethodToHandle(self.handle) # set the content xbmcplugin.setContent(handle=self.handle, content=self.contentType) # make sure we do not cache this one to disc! xbmcplugin.endOfDirectory(self.handle, succeeded=ok, updateListing=replaceExisting, cacheToDisc=False) stopWatch.Lap("items send to Kodi") Logger.Debug("Plugin::Favourites completed. Returned %s item(s)", len(favs)) stopWatch.Stop() except: XbmcWrapper.ShowNotification(LanguageHelper.GetLocalizedString(LanguageHelper.ErrorId), LanguageHelper.GetLocalizedString(LanguageHelper.ErrorList), XbmcWrapper.Error, 4000) Logger.Error("Plugin::Error parsing favourites", exc_info=True) xbmcplugin.endOfDirectory(self.handle, False)
def __UpdateFromUrl(self, url, zipName): """ Update a channel from an URL @param url: The url to download @param zipName: The name to give the download """ Logger.Info("Going to update from %s", url) # wrapper = XbmcDialogProgressWrapper("Updating XOT", url) # destFilename = UriHandler.Download(url, zipName, Config.cacheDir, wrapper.ProgressUpdate) destFilename = UriHandler.Download(url, zipName, Config.cacheDir, self.__RetrieveProgressDummy) Logger.Debug("Download succeeded: %s", destFilename) # we extract to the deploy folder, so with the first start of XOT, the new channel is deployed deployDir = os.path.abspath(os.path.join(Config.rootDir, "deploy")) zipFile = zipfile.ZipFile(destFilename) # now extract first = True Logger.Debug("Extracting %s to %s", destFilename, deployDir) for name in zipFile.namelist(): if first: folder = os.path.split(name)[0] if os.path.exists(os.path.join(deployDir, folder)): shutil.rmtree(os.path.join(deployDir, folder)) first = False if not name.endswith("/") and not name.endswith("\\"): fileName = os.path.join(deployDir, name) path = os.path.dirname(fileName) if not os.path.exists(path): os.makedirs(path) Logger.Debug("Extracting %s", fileName) outfile = open(fileName, 'wb') outfile.write(zipFile.read(name)) outfile.close() zipFile.close() os.remove(destFilename) Logger.Info("Update completed and zip file (%s) removed", destFilename) message = LanguageHelper.GetLocalizedString( LanguageHelper.UpdateCompleteId, splitOnPipes=False) % (zipName.replace(".zip", ""), ) message = message.split("|") XbmcWrapper.ShowNotification(LanguageHelper.GetLocalizedString( LanguageHelper.RestartId), message, displayTime=5000, logger=Logger.Instance())
def AddCategories(self, data): 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.MediaItem("\a.: Categorië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.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) channelText = LanguageHelper.GetLocalizedString(30010) channels = mediaitem.MediaItem(".: %s :." % (channelText, ), "#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 CreateJsonPageItem(self, resultSet): """Creates a new MediaItem for an episode Arguments: resultSet : list[string] - the resultSet of the self.episodeItemRegex Returns: A new MediaItem of type 'folder' This method creates a new MediaItem from the Regular Expression results <resultSet>. The method should be implemented by derived classes and are specific to the channel. """ Logger.Trace(resultSet) if "nextPageUrl" not in resultSet: return None title = "\b.: %s :." % (LanguageHelper.GetLocalizedString(LanguageHelper.MorePages), ) url = "%s%s" % (self.baseUrl, resultSet["nextPageUrl"]) item = mediaitem.MediaItem(title, url) item.icon = self.icon item.thumb = self.noImage item.complete = True return item
def __ConvertMainlistItemToXbmcItem(self, channel, episodeItem, showFavourites, actionUrl=""): Logger.Trace("Converting a mainlist item to XbmcItem with:\nChannel: %s\nItem: %s\nShowFavourites: %s\n" "Actionurl: %s", channel, episodeItem, showFavourites, actionUrl) if actionUrl == "" and showFavourites: raise Exception("Cannot create favourites XbmcItem without actionUrl") item = episodeItem.GetXBMCItem() # add the remove from favourites item: if showFavourites: # XBMC.Container.Refresh refreshes the container and replaces the last history # XBMC.Container.Update updates the container and but appends the new list to the history contextMenuItems = self.__GetContextMenuItems(channel, item=episodeItem, favouritesList=True) else: contextMenuItems = self.__GetContextMenuItems(channel, item=episodeItem) if self.FavouritesEnabled: # add the show favourites here cmdUrl = self.__CreateActionUrl(channel, action=self.actionFavourites) cmd = "XBMC.Container.Update(%s)" % (cmdUrl,) favs = LanguageHelper.GetLocalizedString(LanguageHelper.ChannelFavourites) contextMenuItems.append(('Retro: %s' % (favs, ), cmd)) item.addContextMenuItems(contextMenuItems) if actionUrl == "": url = self.__CreateActionUrl(channel, self.actionListFolder, item=episodeItem) else: Logger.Trace("Using predefined actionUrl") url = actionUrl return url, item, True
def AddPageItems(self, data): """ Adds page items to the main listing @param data: the Parsed Data @return: a tuple of data and items """ Logger.Info("Performing Pre-Processing") items = [] json = JsonHelper(data) totalResults = json.GetValue("totalResults") fromValue = json.GetValue("from") sizeValue = json.GetValue("size") if fromValue + sizeValue < totalResults: morePages = LanguageHelper.GetLocalizedString( LanguageHelper.MorePages) url = self.parentItem.url.split('?')[0] url = "%s?size=%s&from=%s&sort=Nieuwste" % (url, sizeValue, fromValue + sizeValue) Logger.Debug("Adding next-page item from %s to %s", fromValue + sizeValue, fromValue + sizeValue + sizeValue) nextPage = mediaitem.MediaItem(morePages, url) nextPage.icon = self.parentItem.icon nextPage.fanart = self.parentItem.fanart nextPage.thumb = self.parentItem.thumb nextPage.dontGroup = True items.append(nextPage) Logger.Debug("Pre-Processing finished") return json, items
def CreateMoreItem(self, resultSet): """Creates a MediaItem of type 'folder' using the resultSet from the regex. Arguments: resultSet : tuple(strig) - the resultSet of the self.folderItemRegex Returns: A new MediaItem of type 'folder' This method creates a new MediaItem from the Regular Expression or Json results <resultSet>. The method should be implemented by derived classes and are specific to the channel. """ Logger.Trace(resultSet) if resultSet == "klipp" and self.__klippUrlIndicator not in self.parentItem.url: return None more = LanguageHelper.GetLocalizedString(LanguageHelper.MorePages) item = mediaitem.MediaItem(more, "%s&sida=2&embed=true" % (self.parentItem.url, )) item.thumb = self.parentItem.thumb item.icon = self.parentItem.icon item.type = 'folder' item.httpHeaders = self.httpHeaders item.complete = True return item
def CreatePageItem(self, resultSet): """Creates a MediaItem of type 'page' using the resultSet from the regex. Arguments: resultSet : tuple(string) - the resultSet of the self.pageNavigationRegex Returns: A new MediaItem of type 'page' This method creates a new MediaItem from the Regular Expression or Json results <resultSet>. The method should be implemented by derived classes and are specific to the channel. """ Logger.Trace(resultSet) nextPage = resultSet["next"] if not nextPage: Logger.Debug("No more items available") return None more = LanguageHelper.GetLocalizedString(LanguageHelper.MorePages) url = "%s=%s" % (self.parentItem.url.rsplit("=", 1)[0], nextPage) item = mediaitem.MediaItem(more, url) item.thumb = self.parentItem.thumb item.icon = self.icon item.fanart = self.parentItem.fanart item.complete = True return item
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
def CreatePageItem(self, resultSet): """Creates a MediaItem of type 'page' using the resultSet from the regex. Arguments: resultSet : tuple(string) - the resultSet of the self.pageNavigationRegex Returns: A new MediaItem of type 'page' This method creates a new MediaItem from the Regular Expression or Json results <resultSet>. The method should be implemented by derived classes and are specific to the channel. """ Logger.Debug("Starting CreatePageItem") # current page? baseUrl, page = self.parentItem.url.rsplit("=", 1) page = int(page) maxPages = resultSet.get("total_pages", 0) Logger.Trace("Current Page: %d of %d (%s)", page, maxPages, baseUrl) if page + 1 >= maxPages: return None title = LanguageHelper.GetLocalizedString(LanguageHelper.MorePages) url = "%s=%s" % (baseUrl, page + 1) item = mediaitem.MediaItem(title, url) item.fanart = self.parentItem.fanart item.thumb = self.parentItem.thumb return item
def AddClips(self, data): Logger.Info("Adding Clips Pre-Processing") items = [] # if the main list was retrieve using json, are the current data is json, just determine # the clip URL clipUrl = None if data.lstrip().startswith("{"): if self.parentItem.url.endswith("type=program"): # http://playapi.mtgx.tv/v3/videos?format=6723&order=-airdate&type=program # http://playapi.mtgx.tv/v3/videos?format=6723&order=-updated&type=clip" % (dataId,) clipUrl = self.parentItem.url.replace("type=program", "type=clip") else: # now we determine the ID and load the json data dataId = Regexer.DoRegex('data-format-id="(\d+)"', data)[-1] Logger.Debug("Found FormatId = %s", dataId) programUrl = "http://playapi.mtgx.tv/v3/videos?format=%s&order=-airdate&type=program" % ( dataId, ) data = UriHandler.Open(programUrl, proxy=self.proxy) clipUrl = "http://playapi.mtgx.tv/v3/videos?format=%s&order=-updated&type=clip" % ( dataId, ) if clipUrl is not None: clipTitle = LanguageHelper.GetLocalizedString(LanguageHelper.Clips) clipItem = mediaitem.MediaItem("\a.: %s :." % (clipTitle, ), clipUrl) clipItem.thumb = self.noImage items.append(clipItem) Logger.Debug("Pre-Processing finished") return data, items
def __ShowEmptyInformation(self, items, favs=False): """ Adds an empty item to a list or just shows a message. @type favs: boolean indicating that we are dealing with favourites @param items: the list of items @rtype : boolean indicating succes or not """ if self.channelObject: Statistics.RegisterError(self.channelObject) if favs: title = LanguageHelper.GetLocalizedString(LanguageHelper.NoFavsId) else: title = LanguageHelper.GetLocalizedString(LanguageHelper.ErrorNoEpisodes) behaviour = AddonSettings.GetEmptyListBehaviour() Logger.Debug("Showing empty info for mode (favs=%s): [%s]", favs, behaviour) if behaviour == "error": # show error ok = False elif behaviour == "dummy" and not favs: # We should add a dummy items, but not for favs emptyListItem = MediaItem("- %s -" % (title.strip("."), ), "", type='video') emptyListItem.icon = self.channelObject.icon emptyListItem.thumb = self.channelObject.noImage emptyListItem.fanart = self.channelObject.fanart emptyListItem.dontGroup = True emptyListItem.description = "This listing was left empty intentionally." emptyListItem.complete = True emptyListItem.fanart = self.channelObject.fanart # add funny stream here? # part = emptyListItem.CreateNewEmptyMediaPart() # for s, b in YouTube.GetStreamsFromYouTube("", self.channelObject.proxy): # part.AppendMediaStream(s, b) # if we add one, set OK to True ok = True items.append(emptyListItem) else: ok = True XbmcWrapper.ShowNotification(LanguageHelper.GetLocalizedString(LanguageHelper.ErrorId), title, XbmcWrapper.Error, 2500) return ok
def __GetAvailableUpdates(self): """ Opens the addon.xml and fetches all updates. Compares them with the installed versions and returns a list of URL's to download @return: a list of URLs """ data = UriHandler.Open(Config.UpdateUrl.replace(".md5", "")) channels = Regexer.DoRegex( '<addon\W+id="(net.rieter.xot(?:.channel.[^"]+|))\W+version="([^"]+)"', data) updates = [] for channel in channels: addonId = channel[0] addonVersion = channel[1] if addonId == Config.addonId: Logger.Debug("Found main Retrospect version: %s", addonVersion) # the main XOT add-on if Version(version=addonVersion) != Config.version: Logger.Warning( "Not deploying new channels because Retrospect versions do not match: " "Installed %s vs Online %s", Config.version, addonVersion) message = LanguageHelper.GetLocalizedString( LanguageHelper.NewVersion2Id, splitOnPipes=False) message = message % (Config.appName, addonVersion) XbmcWrapper.ShowDialog( LanguageHelper.GetLocalizedString( LanguageHelper.NewVersionId), message.split("|")) return [] else: # set the zipfile name here, but check in the next loop! channelId = "%s-%s" % (addonId, addonVersion) if self.__IsVersionInstalled(addonId, addonVersion): # already installed, continue as if Logger.Info("Update already installed: %s", channelId) continue else: url = "http://www.rieter.net/net.rieter.xot.repository/%s/%s-%s.zip" % ( addonId, addonId, addonVersion) filename = "%s-%s.zip" % (addonId, addonVersion) Logger.Info("New update found: %s @ %s", channelId, url) updates.append((url, filename)) return updates
def Reset(): """ Resets the Vault and Retrospect Machine key, making all encrypted values useless. """ ok = XbmcWrapper.ShowYesNo(LanguageHelper.GetLocalizedString(LanguageHelper.VaultReset), LanguageHelper.GetLocalizedString(LanguageHelper.VaultResetConfirm)) if not ok: Logger.Debug("Aborting Reset Vault") return Logger.Info("Resetting the vault to a new initial state.") AddonSettings.SetSetting(Vault.__APPLICATION_KEY_SETTING, "") # create a vault instance so we initialize a new one with a new PIN. Vault() return
def CtMnTestProxy(self, item): # :@UnusedVariable """ Checks if the proxy is OK""" if not self.proxy: message = "Proxy not configured: %s" % (self.proxy,) else: url = Config.UpdateUrl + "proxy" data = UriHandler.Open(url, proxy=self.proxy) # Logger.Trace(data) if data == "1": message = LanguageHelper.GetLocalizedString(LanguageHelper.ProxyOkId) % (self.proxy,) else: message = LanguageHelper.GetLocalizedString(LanguageHelper.ProxyNokId) % (self.proxy,) Logger.Debug(message) XbmcWrapper.ShowDialog("", message) pass
def CreatePageItem(self, resultSet): items = [] if 'next' in resultSet: title = LanguageHelper.GetLocalizedString(LanguageHelper.MorePages) url = resultSet['next'] item = mediaitem.MediaItem(title, url) item.fanart = self.parentItem.fanart item.thumb = self.parentItem.thumb items.append(item) return items
def CreatePageItem(self, resultSet): """Creates a MediaItem of type 'page' using the resultSet from the regex. Arguments: resultSet : tuple(string) - the resultSet of the self.pageNavigationRegex Returns: A new MediaItem of type 'page' This method creates a new MediaItem from the Regular Expression or Json results <resultSet>. The method should be implemented by derived classes and are specific to the channel. """ if "totalPages" not in resultSet: return None Logger.Debug("Starting CreatePageItem") # current page? pageUriPart = "page%5Bnumber%5D=" if pageUriPart not in self.parentItem.url: page = 1 urlFormat = "{0}&page%5Bnumber%5D={{0:d}}".format( self.parentItem.url) else: baseUrl, pagePart = self.parentItem.url.rsplit(pageUriPart, 1) nextPart = pagePart.find("&") if nextPart < 0: # end page = int(pagePart) urlFormat = "{0}&page%5Bnumber%5D={{0:d}}".format(baseUrl) else: page = int(pagePart[0:nextPart]) urlFormat = "{0}&page%5Bnumber%5D={{0:d}}&{1}".format( baseUrl, pagePart[nextPart:]) maxPages = resultSet.get("totalPages", 0) Logger.Trace("Current Page: %d of %d (%s)", page, maxPages, self.parentItem.url) if page + 1 > maxPages: return None title = LanguageHelper.GetLocalizedString(LanguageHelper.MorePages) url = urlFormat.format(page + 1) item = mediaitem.MediaItem(title, url) item.fanart = self.parentItem.fanart item.thumb = self.parentItem.thumb return item
def IsInstallMethodValid(self, config): """ Validates that Retrospect is installed using the repository. If not it will popup a dialog box. Arguments: config : Config - The Retrospect config object. """ repoAvailable = self.__IsRepoAvailable(config) if not repoAvailable: # show alert if self.logger: self.logger.Warning( "No Respository installed. Reminding user to install it.") XbmcWrapper.ShowDialog( LanguageHelper.GetLocalizedString( LanguageHelper.RepoWarningId), LanguageHelper.GetLocalizedString( LanguageHelper.RepoWarningDetailId)) return repoAvailable
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)
def CreateFolderItem(self, resultSet): """Creates a MediaItem of type 'folder' using the resultSet from the regex. Arguments: resultSet : tuple(strig) - the resultSet of the self.folderItemRegex Returns: A new MediaItem of type 'folder' This method creates a new MediaItem from the Regular Expression or Json results <resultSet>. The method should be implemented by derived classes and are specific to the channel. """ Logger.Trace(resultSet) resultSet["title"] = LanguageHelper.GetLocalizedString( LanguageHelper.MorePages) return chn_class.Channel.CreateFolderItem(self, resultSet)
def AddVideoPageItemsJson(self, data): items = [] json = JsonHelper(data) currentOffset = json.GetValue("request", "offset") or 0 itemsOnThisPage = len(json.GetValue("response", "items") or []) totalItems = json.GetValue("response", "total") if totalItems > currentOffset + itemsOnThisPage: # add next page items newOffset = currentOffset + itemsOnThisPage seriesId = json.GetValue("request", "parentSeriesOID")[0] url = "https://vod.medialaan.io/api/1.0/list?app_id=%s&parentSeriesOID=%s&offset=%s" % (self.__app, seriesId, newOffset) more = LanguageHelper.GetLocalizedString(LanguageHelper.MorePages) item = MediaItem(more, url) item.thumb = self.noImage item.icon = self.icon item.fanart = self.parentItem.fanart item.complete = True items.append(item) return json, items
def LogOn(self): if self.__idToken: return True # check if there is a refresh token # refresh token: viervijfzes_refresh_token refreshToken = AddonSettings.GetSetting("viervijfzes_refresh_token") client = AwsIdp("eu-west-1_dViSsKM5Y", "6s1h851s8uplco5h6mqh1jac8m", proxy=self.proxy, logger=Logger.Instance()) if refreshToken: idToken = client.RenewToken(refreshToken) if idToken: self.__idToken = idToken return True else: Logger.Info("Extending token for VierVijfZes failed.") # username: viervijfzes_username username = AddonSettings.GetSetting("viervijfzes_username") # password: viervijfzes_password v = Vault() password = v.GetSetting("viervijfzes_password") if not username or not password: XbmcWrapper.ShowDialog( title=None, lines=LanguageHelper.GetLocalizedString( LanguageHelper.MissingCredentials), ) return False idToken, refreshToken = client.Authenticate(username, password) if not idToken or not refreshToken: Logger.Error("Error getting a new token. Wrong password?") return False self.__idToken = idToken AddonSettings.SetSetting("viervijfzes_refresh_token", refreshToken) return True
def AlphaListing(self, data): """Performs pre-process actions for data processing Arguments: data : string - the retrieve data that was loaded for the current item and URL. Returns: A tuple of the data and a list of MediaItems that were generated. Accepts an data from the ProcessFolderList 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 ("", []). """ Logger.Info("Generating an Alpha list for NPO") items = [] # https://www.npo.nl/media/series?page=1&dateFrom=2014-01-01&tilemapping=normal&tiletype=teaser # https://www.npo.nl/media/series?page=2&dateFrom=2014-01-01&az=A&tilemapping=normal&tiletype=teaser # https://www.npo.nl/media/series?page=2&dateFrom=2014-01-01&az=0-9&tilemapping=normal&tiletype=teaser titleFormat = LanguageHelper.GetLocalizedString(LanguageHelper.StartWith) urlFormat = "https://www.npo.nl/media/series?page=1&dateFrom=2014-01-01&az=%s&tilemapping=normal&tiletype=teaser&pageType=catalogue" for char in "ABCDEFGHIJKLMNOPQRSTUVWXYZ0": if char == "0": char = "0-9" subItem = mediaitem.MediaItem(titleFormat % (char,), urlFormat % (char, )) subItem.complete = True subItem.icon = self.icon subItem.thumb = self.noImage subItem.dontGroup = True subItem.HttpHeaders = {"X-Requested-With": "XMLHttpRequest"} items.append(subItem) return data, items
def AddPages(self, data): """Performs pre-process actions for data processing Arguments: data : string - the retrieve data that was loaded for the current item and URL. Returns: A tuple of the data and a list of MediaItems that were generated. Accepts an data from the ProcessFolderList 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 ("", []). """ Logger.Info("Adding pages") # extract the current page from: # http://www.foxsports.nl/video/filter/fragments/1/alle/tennis/ currentPages = Regexer.DoRegex('(.+filter/fragments)/(\d+)/(.+)', self.parentItem.url) if not currentPages: return data, [] currentPage = currentPages[0] items = [] url = "%s/%s/%s" % (currentPage[0], int(currentPage[1]) + 1, currentPage[2]) pageItem = mediaitem.MediaItem(LanguageHelper.GetLocalizedString(LanguageHelper.MorePages), url) pageItem.fanart = self.parentItem.fanart pageItem.thumb = self.parentItem.thumb pageItem.dontGroup = True items.append(pageItem) return data, items
def AlphaListing(self, data): """Performs pre-process actions for data processing Arguments: data : string - the retrieve data that was loaded for the current item and URL. Returns: A tuple of the data and a list of MediaItems that were generated. Accepts an data from the ProcessFolderList 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 ("", []). """ Logger.Info("Generating an Alpha list for NPO") items = [] titleFormat = LanguageHelper.GetLocalizedString(LanguageHelper.StartWith) for char in "ABCDEFGHIJKLMNOPQRSTUVWXYZ0": if char == "0": char = "0-9" subItem = mediaitem.MediaItem(titleFormat % (char,), "http://www.npo.nl/a-z?page=1") else: subItem = mediaitem.MediaItem(titleFormat % (char,), "http://www.npo.nl/a-z/%s?page=1" % (char.lower(),)) subItem.complete = True subItem.icon = self.icon subItem.thumb = self.noImage subItem.dontGroup = True items.append(subItem) return data, items
def SetSetting(self, settingId, settingName=None, settingActionId=None): # type: (str, str) -> None """ Reads a value for a setting from the keyboard and encryptes it in the Kodi Add-on settings @param settingId: the ID for the Kodi Add-on setting to set @param settingName: the name to display in the keyboard @param settingActionId: the name of the action that was called. The setttingActionId defaults to <settingId>_set """ Logger.Info("Encrypting value for setting '%s'", settingId) inputValue = XbmcWrapper.ShowKeyBoard( "", LanguageHelper.GetLocalizedString(LanguageHelper.VaultSpecifySetting) % (settingName or settingId, )) if inputValue is None: Logger.Debug("Setting of encrypted value cancelled.") return value = "%s=%s" % (settingId, inputValue) encryptedValue = self.__Encrypt(value, Vault.__Key) if settingActionId is None: settingActionId = "%s_set" % (settingId,) Logger.Debug("Updating '%s' and '%s'", settingId, settingActionId) AddonSettings.SetSetting(settingId, encryptedValue) if inputValue: AddonSettings.SetSetting(settingActionId, "******") else: AddonSettings.SetSetting(settingActionId, "") Logger.Info("Successfully encrypted value for setting '%s'", settingId) return
def UpdateVideoItem(self, item): """Updates an existing MediaItem with more data. Arguments: item : MediaItem - the MediaItem that needs to be updated Returns: The original item with more data added to it's properties. 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. """ Logger.Debug('Starting UpdateVideoItem for %s (%s)', item.name, self.channelName) data = UriHandler.Open(item.url, proxy=self.proxy) Logger.Trace(data) if 'livestart":-' in data: Logger.Debug("Live item that has not yet begun.") json = JsonHelper(data, Logger.Instance()) secondsToStart = json.GetValue("video", "livestart") if secondsToStart: secondsToStart = -int(secondsToStart) Logger.Debug("Seconds till livestream: %s", secondsToStart) timeLeft = "%s:%02d:%02d" % (secondsToStart / 3600, (secondsToStart % 3600) / 60, secondsToStart % 60) Logger.Debug("Live items starts at %s", timeLeft) lines = list(LanguageHelper.GetLocalizedString(LanguageHelper.NoLiveStreamId)) lines[-1] = "%s ETA: %s" % (lines[-1], timeLeft) XbmcWrapper.ShowDialog(LanguageHelper.GetLocalizedString(LanguageHelper.NoLiveStreamTitleId), lines) else: XbmcWrapper.ShowDialog(LanguageHelper.GetLocalizedString(LanguageHelper.NoLiveStreamTitleId), LanguageHelper.GetLocalizedString(LanguageHelper.NoLiveStreamId)) return item item.MediaItemParts = [] mediaPart = item.CreateNewEmptyMediaPart() spoofIp = self._GetSetting("spoof_ip", "0.0.0.0") if spoofIp is not None: mediaPart.HttpHeaders["X-Forwarded-For"] = spoofIp # mediaPart.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:17.0) Gecko/20100101 Firefox/17.0" # isLive = False if '"live":true' in data or "/live/" in item.url: mediaPart.AddProperty("IsLive", "true") Logger.Debug("Live video item found.") # isLive = True else: Logger.Debug("Normal (not live, or possible was live) video item found") # replace items #videos = map(lambda v: self.__ReplaceClist(v), videos) jsonVideoData = JsonHelper(data) videos = jsonVideoData.GetValue("video", "videoReferences") # videos = Regexer.DoRegex(self.mediaUrlRegex, data) for video in videos: playerType = video.get("playerType", "") if "dash" in playerType: continue if video["url"].startswith("rtmp"): # just replace some data in the URL mediaPart.AppendMediaStream(self.GetVerifiableVideoUrl(video["url"]).replace("_definst_", "?slist="), video[1]) elif "m3u8" in video["url"]: Logger.Info("SVTPlay.se m3u8 stream found: %s", video["url"]) # apparently the m3u8 do not work well for server www0.c91001.dna.qbrick.com if "www0.c91001.dna.qbrick.com" in video["url"]: continue # m3u8 we need to parse. Get more streams from this file. videoUrl = video["url"] altIndex = videoUrl.find("m3u8?") # altIndex = videoUrl.find("~uri") if altIndex > 0: videoUrl = videoUrl[0:altIndex + 4] for s, b in M3u8.GetStreamsFromM3u8(videoUrl, self.proxy, headers=mediaPart.HttpHeaders): item.complete = True mediaPart.AppendMediaStream(s, b) elif "f4m" in video["url"]: Logger.Info("SVTPlay.se manifest.f4m stream found: %s", video["url"]) #if "manifest.f4m?start=" in video["url"]: # # this was a live stream, convert it to M3u8 # # http://svt06-lh.akamaihd.net/z/svt06_0@77501/manifest.f4m?start=1386566700&end=1386579600 # # to # # http://svt06hls-lh.akamaihd.net/i/svt06_0@77501/master.m3u8?__b__=563&start=1386566700&end=1386579600 # m3u8Url = video["url"].replace("-lh.akamaihd.net/z", "hls-lh.akamaihd.net/i").replace("manifest.f4m?", "master.m3u8?__b__=563&") # Logger.Info("Found f4m stream for an old Live stream. Converting to M3U8:\n%s -to -\n%s", video["url"], m3u8Url) # videos.append((m3u8Url, 0)) # continue # for now we skip these as they do not yet work with XBMC continue # http://svtplay8m-f.akamaihd.net/z/se/krypterat/20120830/254218/LILYHAMMER-003A-mp4-,c,d,b,e,-v1-4bc7ecc090b19c82.mp4.csmil/manifest.f4m?hdcore=2.8.0&g=TZOMVRTEILSE #videoDataUrl = video["url"] # videoUrl = "%s?hdcore=2.8.0&g=TZOMVRTEILSE" % (videoDataUrl,) #videoUrl = "%s?hdcore=2.10.3&g=IJGTWSVWPPKH" % (videoDataUrl,) # metaData = UriHandler.Open(videoUrl, proxy=self.proxy, referer=self.swfUrl) # Logger.Debug(metaData) # The referer seems to be unimportant # header = "referer=%s" % (urllib.quote(self.swfUrl),) # videoUrl = "%s|%s" % (videoUrl, header) #mediaPart.AppendMediaStream(videoUrl, video[1]) else: Logger.Info("SVTPlay.se standard HTTP stream found.") # else just use the URL mediaPart.AppendMediaStream(video["url"], video["bitrate"]) subtitle = Regexer.DoRegex('"url":"([^"]+.wsrt)"|"url":"(http://media.svt.se/download/[^"]+.m3u8)', data) for sub in subtitle: if sub[-1]: Logger.Info("Found M3u8 subtitle, replacing with WSRT") start, name, index = sub[-1].rsplit("/", 2) subUrl = "%s/%s/%s.wsrt" % (start, name, name) else: subUrl = sub[0] mediaPart.Subtitle = subtitlehelper.SubtitleHelper.DownloadSubtitle(subUrl, format="srt", proxy=self.proxy) item.complete = True return item