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 __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(": "))
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 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()
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 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 __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 __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()
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
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
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 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 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 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
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 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
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 __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 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 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 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 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 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 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
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 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
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
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 __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