def __init__(self, addon_name, handle, params): """ :param str addon_name: The name of the add-on :param int handle: The handle for this run :param str params: The parameters used to start the ActionParser """ Logger.debug("Parsing parameters from: %s", params) self.handle = int(handle) # determine the query parameters self._params = params self.params = self.__get_parameters(params) self.pluginName = addon_name # We need a picker for this instance self.pickler = Pickler(Config.profileDir) # Field for property self.__media_item = None # For remote debugging and log reading purpose we need the full pickle string. if Logger.instance().minLogLevel <= Logger.LVL_DEBUG \ and self.media_item is not None \ and self.pickler.is_pickle_store_id(self.params[keyword.PICKLE]): Logger.debug("Replacing PickleStore pickle '%s' with full pickle", self.params[keyword.PICKLE]) self.params[keyword.PICKLE] = self.pickler.pickle_media_item(self.media_item)
def __init__(self, addon_name, params): """ :param str addon_name: The name of the add-on :param str params: The parameteters used to start the ParameterParser """ Logger.debug("Parsing parameters from: %s", params) # Url Keywords self.keywordPickle = "pickle" # : Used for the pickle item self.keywordAction = "action" # : Used for specifying the action self.keywordChannel = "channel" # : Used for the channel self.keywordChannelCode = "channelcode" # : Used for the channelcode self.keywordCategory = "category" # : Used for the category self.keywordRandomLive = "rnd" # : Used for randomizing live items self.keywordSettingId = "settingid" # : Used for setting an encrypted setting self.keywordSettingActionId = "settingactionid" # : Used for passing the actionid for the encryption self.keywordSettingName = "settingname" # : Used for setting an encrypted settings display name self.keywordSettingTabFocus = "tabfocus" # : Used for setting the tabcontrol to focus after changing a setting self.keywordSettingSettingFocus = "settingfocus" # : Used for setting the setting control to focus after changing a setting self.keywordLanguage = "lang" # : Used for the 2 char language information self.keywordProxy = "proxy" # : Used so set the proxy index self.keywordLocalIP = "localip" # : Used to set the local ip index # Url Actions self.actionFavourites = "favourites" # : Used to show favorites for a channel self.actionAllFavourites = "allfavourites" # : Used to show all favorites self.actionRemoveFavourite = "removefromfavourites" # : Used to remove items from favorites self.actionAddFavourite = "addtofavourites" # : Used to add items to favorites self.actionDownloadVideo = "downloadVideo" # : Used to download a video item self.actionPlayVideo = "playvideo" # : Used to play a video item self.actionUpdateChannels = "updatechannels" # : Used to update channels self.actionListFolder = "listfolder" # : Used to list a folder self.actionListCategory = "listcategory" # : Used to show the channels from a category self.actionConfigureChannel = "configurechannel" # : Used to configure a channel self.actionSetEncryptionPin = "changepin" # : Used for setting an application pin self.actionSetEncryptedValue = "encryptsetting" # : Used for setting an application pin self.actionResetVault = "resetvault" # : Used for resetting the vault self.actionPostLog = "postlog" # : Used for sending log files to pastebin.com self.actionProxy = "setproxy" # : Used for setting a proxy self.propertyRetrospect = "Retrospect" self.propertyRetrospectChannel = "RetrospectChannel" self.propertyRetrospectChannelSetting = "RetrospectChannelSettings" self.propertyRetrospectFolder = "RetrospectFolder" self.propertyRetrospectVideo = "RetrospectVideo" self.propertyRetrospectCloaked = "RetrospectCloaked" self.propertyRetrospectCategory = "RetrospectCategory" self.propertyRetrospectFavorite = "RetrospectFavorite" self.propertyRetrospectAdaptive = "RetrospectAdaptive" # determine the query parameters self.params = self.__get_parameters(params) self.pluginName = addon_name # We need a picker for this instance self._pickler = Pickler()
def __init__(self, path): """ Initializes a Favourites class that can be use to show, add and delete favourites. :param str path: The path to store the favourites file """ self.__filePattern = "%s-%s.xotfav" self.__pickler = Pickler() self.FavouriteFolder = path
class ActionParser(object): # Mapping from old to new __lookup = { "chn_nos2010": "channel.nos.nos2010", "chn_een": "channel.be.een", "chn_ketnet": "channel.be.ketnet", "chn_rtbf": "channel.be.rtbf", "chn_sporza": "channel.be.sporza", "chn_vier": "channel.be.vier", "chn_vrtnu": "channel.be.vrtnu", "chn_vtm": "channel.be.vtm", "chn_vtmbe": "channel.be.vtmbe", "chn_srf": "channel.de.srf", "chn_tvse": "channel.mtg.tvse", "chn_viafree": "channel.mtg.viafree", "chn_mtvnl": "channel.mtv.mtvnl", "chn_southpark": "channel.mtv.southpark", "chn_nickelodeon": "channel.nick.nickelodeon", "chn_nickjr": "channel.nick.nickjr", "chn_nrkno": "channel.no.nrkno", "chn_nosnl": "channel.nos.nosnl", "chn_schooltv": "channel.nos.schooltv", "chn_at5": "channel.regionalnl.at5", "chn_flevo": "channel.regionalnl.flevo", "chn_gelderland": "channel.regionalnl.gelderland", "chn_l1": "channel.regionalnl.l1", "chn_lokaal": "channel.regionalnl.lokaal", "chn_rpoapp": "channel.regionalnl.rpoapp", "chn_rtl": "channel.rtlnl.rtl", "chn_kijknl": "channel.sbsnl.kijknl", "chn_oppetarkiv": "channel.se.oppetarkiv", "chn_sbs": "channel.se.sbs", "chn_svt": "channel.se.svt", "chn_tv4se": "channel.se.tv4se", "chn_urplay": "channel.se.urplay", "chn_24classic": "channel.streams.24classic", "chn_radio538": "channel.streams.radio538", "chn_bbc": "channel.uk.bbc", "chn_amt": "channel.videos.amt", "chn_channel9": "channel.videos.channel9", "chn_dumpert": "channel.videos.dumpert", "chn_eredivisie": "channel.videos.eredivisie", "chn_extreme": "channel.videos.extreme", "chn_hardwareinfo": "channel.videos.hardwareinfo", "chn_ons": "channel.videos.ons", "chn_pathenl": "channel.videos.pathenl", "chn_twit": "channel.videos.twit" } def __init__(self, addon_name, handle, params): """ :param str addon_name: The name of the add-on :param int handle: The handle for this run :param str params: The parameters used to start the ActionParser """ Logger.debug("Parsing parameters from: %s", params) self.handle = int(handle) # determine the query parameters self._params = params self.params = self.__get_parameters(params) self.pluginName = addon_name # We need a picker for this instance self.pickler = Pickler(Config.profileDir) # Field for property self.__media_item = None # For remote debugging and log reading purpose we need the full pickle string. if Logger.instance().minLogLevel <= Logger.LVL_DEBUG \ and self.media_item is not None \ and self.pickler.is_pickle_store_id(self.params[keyword.PICKLE]): Logger.debug("Replacing PickleStore pickle '%s' with full pickle", self.params[keyword.PICKLE]) self.params[keyword.PICKLE] = self.pickler.pickle_media_item(self.media_item) @property def media_item(self): """ The current MediaItem :returns: The current MediaItem :rtype: MediaItem """ if self.__media_item is None and keyword.PICKLE in self.params: self.__media_item = self.pickler.de_pickle_media_item(self.params[keyword.PICKLE]) return self.__media_item def create_action_url(self, channel, action, item=None, store_id=None, category=None): """ Creates an URL that includes an action. Arguments: channel : Channel - action : string - Keyword Arguments: item : MediaItem - :param ChannelInfo|Channel channel: The channel object to use for the URL :param str action: Action to create an url for :param MediaItem item: The media item to add :param str store_id: The ID of the pickle store :param str category: The category to use :return: a complete action url with all keywords and values :rtype: str|unicode """ if action is None: raise Exception("action is required") # catch the plugin:// url's for items and channels. if item is not None and item.url and item.url.startswith("plugin://"): return item.url if item is None and channel is not None and channel.uses_external_addon: return channel.addonUrl params = dict() if channel: params[keyword.CHANNEL] = channel.url_id params[keyword.ACTION] = action # it might have an item or not if item is not None: params[keyword.PICKLE] = "{}--{}".format(store_id, item.guid) if action == PLAY_VIDEO and item.isLive: params[keyword.RANDOM_LIVE] = random.randint(10000, 99999) if category: params[keyword.CATEGORY] = category url = "%s?" % (self.pluginName, ) for k in params.keys(): url = "%s%s=%s&" % (url, k, params[k]) url = url.strip('&') # Logger.Trace("Created url: '%s'", url) return url def get_parent_guid(self, channel, parent_item): """ Returns the parent guid of an item :param channel: The parent channel object :param parent_item: The parent items :return: a guid of either the parent channel or item :rtype: str """ if channel is None and parent_item is None: # we should not use the store return None return channel.guid if parent_item is None else parent_item.guid def __get_parameters(self, query_string): """ Extracts the actual parameters as a dictionary from the passed in querystring. This method takes the self.quotedPlus into account. :param str query_string: The querystring :return: dict() of keywords and values. :rtype: dict[str,str|None] """ result = dict() query_string = query_string.strip('?') if query_string == '': return result try: for pair in query_string.split("&"): (k, v) = pair.split("=") result[k] = v # if the channelcode was empty, it was stripped, add it again. if keyword.CHANNEL in result and "-" in result[keyword.CHANNEL]: id_parts = result[keyword.CHANNEL].split("-") result[keyword.CHANNEL] = id_parts[0] result[keyword.CHANNEL_CODE] = id_parts[1] elif keyword.CHANNEL in result and "." not in result[keyword.CHANNEL]: result[keyword.CHANNEL] = ActionParser.__lookup[result[keyword.CHANNEL]] if keyword.CHANNEL_CODE not in result: Logger.debug("Adding ChannelCode=None as it was missing from the dict: %s", result) result[keyword.CHANNEL_CODE] = None except: Logger.critical("Cannot determine query strings from %s", query_string, exc_info=True) raise return result def __str__(self): return "Plugin Params: {} ({})\n" \ "Handle: {}\n" \ "Name: {}\n" \ "Query: {}".format(self.params, len(self.params), self.handle, self.pluginName, self._params)
class ParameterParser(object): def __init__(self, addon_name, handle, params): """ :param str addon_name: The name of the add-on :param int handle: The handle for this run :param str params: The parameteters used to start the ParameterParser """ Logger.debug("Parsing parameters from: %s", params) # Url Keywords self.keywordPickle = "pickle" # : Used for the pickle item self.keywordAction = "action" # : Used for specifying the action self.keywordChannel = "channel" # : Used for the channel self.keywordChannelCode = "channelcode" # : Used for the channelcode self.keywordCategory = "category" # : Used for the category self.keywordRandomLive = "rnd" # : Used for randomizing live items self.keywordSettingId = "settingid" # : Used for setting an encrypted setting self.keywordSettingActionId = "settingactionid" # : Used for passing the actionid for the encryption self.keywordSettingName = "settingname" # : Used for setting an encrypted settings display name self.keywordSettingTabFocus = "tabfocus" # : Used for setting the tabcontrol to focus after changing a setting self.keywordSettingSettingFocus = "settingfocus" # : Used for setting the setting control to focus after changing a setting self.keywordLanguage = "lang" # : Used for the 2 char language information self.keywordProxy = "proxy" # : Used so set the proxy index self.keywordLocalIP = "localip" # : Used to set the local ip index # Url Actions self.actionFavourites = "favourites" # : Used to show favorites for a channel self.actionAllFavourites = "allfavourites" # : Used to show all favorites self.actionRemoveFavourite = "removefromfavourites" # : Used to remove items from favorites self.actionAddFavourite = "addtofavourites" # : Used to add items to favorites self.actionDownloadVideo = "downloadVideo" # : Used to download a video item self.actionPlayVideo = "playvideo" # : Used to play a video item self.actionUpdateChannels = "updatechannels" # : Used to update channels self.actionListFolder = "listfolder" # : Used to list a folder self.actionListCategory = "listcategory" # : Used to show the channels from a category self.actionConfigureChannel = "configurechannel" # : Used to configure a channel self.actionSetEncryptionPin = "changepin" # : Used for setting an application pin self.actionSetEncryptedValue = "encryptsetting" # : Used for setting an application pin self.actionResetVault = "resetvault" # : Used for resetting the vault self.actionPostLog = "postlog" # : Used for sending log files to pastebin.com self.actionProxy = "setproxy" # : Used for setting a proxy self.handle = int(handle) # determine the query parameters self._params = params self.params = self.__get_parameters(params) self.pluginName = addon_name # We need a picker for this instance self._pickler = Pickler(Config.profileDir) # Field for property self.__media_item = None # For remote debugging and log reading purpose we need the full pickle string. if Logger.instance().minLogLevel <= Logger.LVL_DEBUG \ and self.media_item is not None \ and self._pickler.is_pickle_store_id(self.params[self.keywordPickle]): Logger.debug("Replacing PickleStore pickle '%s' with full pickle", self.params[self.keywordPickle]) self.params[self.keywordPickle] = self._pickler.pickle_media_item( self.media_item) @property def media_item(self): if self.__media_item is None and self.keywordPickle in self.params: self.__media_item = self._pickler.de_pickle_media_item( self.params[self.keywordPickle]) return self.__media_item def _create_action_url(self, channel, action, item=None, store_id=None, category=None): """ Creates an URL that includes an action. Arguments: channel : Channel - action : string - Keyword Arguments: item : MediaItem - :param ChannelInfo|Channel channel: The channel object to use for the URL :param str action: Action to create an url for :param MediaItem item: The media item to add :param str store_id: The ID of the pickle store :param str category: The category to use :return: a complete action url with all keywords and values :rtype: str|unicode """ if action is None: raise Exception("action is required") # catch the plugin:// url's for items and channels. if item is not None and item.url and item.url.startswith("plugin://"): return item.url if item is None and channel is not None and channel.uses_external_addon: return channel.addonUrl params = dict() if channel: params[self.keywordChannel] = channel.moduleName if channel.channelCode: params[self.keywordChannelCode] = channel.channelCode params[self.keywordAction] = action # it might have an item or not if item is not None: params[self.keywordPickle] = "{}--{}".format(store_id, item.guid) if action == self.actionPlayVideo and item.isLive: params[self.keywordRandomLive] = random.randint(10000, 99999) if category: params[self.keywordCategory] = category url = "%s?" % (self.pluginName, ) for k in params.keys(): url = "%s%s=%s&" % (url, k, params[k]) url = url.strip('&') # Logger.Trace("Created url: '%s'", url) return url def _get_parent_guid(self, channel, parent_item): """ Returns the parent guid of an item :param channel: The parent channel object :param parent_item: The parent items :return: a guid of either the parent channel or item :rtype: str """ if channel is None and parent_item is None: # we should not use the store return None return channel.guid if parent_item is None else parent_item.guid def __get_parameters(self, query_string): """ Extracts the actual parameters as a dictionary from the passed in querystring. This method takes the self.quotedPlus into account. :param str query_string: The querystring :return: dict() of keywords and values. :rtype: dict[str,str|None] """ result = dict() query_string = query_string.strip('?') if query_string == '': return result try: for pair in query_string.split("&"): (k, v) = pair.split("=") result[k] = v # if the channelcode was empty, it was stripped, add it again. if self.keywordChannelCode not in result: Logger.debug( "Adding ChannelCode=None as it was missing from the dict: %s", result) result[self.keywordChannelCode] = None except: Logger.critical("Cannot determine query strings from %s", query_string, exc_info=True) raise return result def __str__(self): return "Plugin Params: {} ({})\n" \ "Handle: {}\n" \ "Name: {}\n" \ "Query: {}".format(self.params, len(self.params), self.handle, self.pluginName, self._params)
def __init__(self, addon_name, handle, params): """ :param str addon_name: The name of the add-on :param int handle: The handle for this run :param str params: The parameteters used to start the ParameterParser """ Logger.debug("Parsing parameters from: %s", params) # Url Keywords self.keywordPickle = "pickle" # : Used for the pickle item self.keywordAction = "action" # : Used for specifying the action self.keywordChannel = "channel" # : Used for the channel self.keywordChannelCode = "channelcode" # : Used for the channelcode self.keywordCategory = "category" # : Used for the category self.keywordRandomLive = "rnd" # : Used for randomizing live items self.keywordSettingId = "settingid" # : Used for setting an encrypted setting self.keywordSettingActionId = "settingactionid" # : Used for passing the actionid for the encryption self.keywordSettingName = "settingname" # : Used for setting an encrypted settings display name self.keywordSettingTabFocus = "tabfocus" # : Used for setting the tabcontrol to focus after changing a setting self.keywordSettingSettingFocus = "settingfocus" # : Used for setting the setting control to focus after changing a setting self.keywordLanguage = "lang" # : Used for the 2 char language information self.keywordProxy = "proxy" # : Used so set the proxy index self.keywordLocalIP = "localip" # : Used to set the local ip index # Url Actions self.actionFavourites = "favourites" # : Used to show favorites for a channel self.actionAllFavourites = "allfavourites" # : Used to show all favorites self.actionRemoveFavourite = "removefromfavourites" # : Used to remove items from favorites self.actionAddFavourite = "addtofavourites" # : Used to add items to favorites self.actionDownloadVideo = "downloadVideo" # : Used to download a video item self.actionPlayVideo = "playvideo" # : Used to play a video item self.actionUpdateChannels = "updatechannels" # : Used to update channels self.actionListFolder = "listfolder" # : Used to list a folder self.actionListCategory = "listcategory" # : Used to show the channels from a category self.actionConfigureChannel = "configurechannel" # : Used to configure a channel self.actionSetEncryptionPin = "changepin" # : Used for setting an application pin self.actionSetEncryptedValue = "encryptsetting" # : Used for setting an application pin self.actionResetVault = "resetvault" # : Used for resetting the vault self.actionPostLog = "postlog" # : Used for sending log files to pastebin.com self.actionProxy = "setproxy" # : Used for setting a proxy self.handle = int(handle) # determine the query parameters self._params = params self.params = self.__get_parameters(params) self.pluginName = addon_name # We need a picker for this instance self._pickler = Pickler(Config.profileDir) # Field for property self.__media_item = None # For remote debugging and log reading purpose we need the full pickle string. if Logger.instance().minLogLevel <= Logger.LVL_DEBUG \ and self.media_item is not None \ and self._pickler.is_pickle_store_id(self.params[self.keywordPickle]): Logger.debug("Replacing PickleStore pickle '%s' with full pickle", self.params[self.keywordPickle]) self.params[self.keywordPickle] = self._pickler.pickle_media_item( self.media_item)
class ActionParser(object): def __init__(self, addon_name, handle, params): """ :param str addon_name: The name of the add-on :param int handle: The handle for this run :param str params: The parameters used to start the ActionParser """ Logger.debug("Parsing parameters from: %s", params) self.handle = int(handle) # determine the query parameters self._params = params self.params = self.__get_parameters(params) self.pluginName = addon_name # We need a picker for this instance self.pickler = Pickler(Config.profileDir) # Field for property self.__media_item = None # For remote debugging and log reading purpose we need the full pickle string. if Logger.instance().minLogLevel <= Logger.LVL_DEBUG \ and self.media_item is not None \ and self.pickler.is_pickle_store_id(self.params[keyword.PICKLE]): Logger.debug("Replacing PickleStore pickle '%s' with full pickle", self.params[keyword.PICKLE]) self.params[keyword.PICKLE] = self.pickler.pickle_media_item( self.media_item) @property def media_item(self): """ The current MediaItem :returns: The current MediaItem :rtype: MediaItem """ if self.__media_item is None and keyword.PICKLE in self.params: self.__media_item = self.pickler.de_pickle_media_item( self.params[keyword.PICKLE]) return self.__media_item def create_action_url(self, channel, action, item=None, store_id=None, category=None): """ Creates an URL that includes an action. Arguments: channel : Channel - action : string - Keyword Arguments: item : MediaItem - :param ChannelInfo|Channel channel: The channel object to use for the URL :param str action: Action to create an url for :param MediaItem item: The media item to add :param str store_id: The ID of the pickle store :param str category: The category to use :return: a complete action url with all keywords and values :rtype: str|unicode """ if action is None: raise Exception("action is required") # catch the plugin:// url's for items and channels. if item is not None and item.url and item.url.startswith("plugin://"): return item.url if item is None and channel is not None and channel.uses_external_addon: return channel.addonUrl params = dict() if channel: params[keyword.CHANNEL] = channel.moduleName if channel.channelCode: params[keyword.CHANNEL_CODE] = channel.channelCode params[keyword.ACTION] = action # it might have an item or not if item is not None: params[keyword.PICKLE] = "{}--{}".format(store_id, item.guid) if action == PLAY_VIDEO and item.isLive: params[keyword.RANDOM_LIVE] = random.randint(10000, 99999) if category: params[keyword.CATEGORY] = category url = "%s?" % (self.pluginName, ) for k in params.keys(): url = "%s%s=%s&" % (url, k, params[k]) url = url.strip('&') # Logger.Trace("Created url: '%s'", url) return url def get_parent_guid(self, channel, parent_item): """ Returns the parent guid of an item :param channel: The parent channel object :param parent_item: The parent items :return: a guid of either the parent channel or item :rtype: str """ if channel is None and parent_item is None: # we should not use the store return None return channel.guid if parent_item is None else parent_item.guid def __get_parameters(self, query_string): """ Extracts the actual parameters as a dictionary from the passed in querystring. This method takes the self.quotedPlus into account. :param str query_string: The querystring :return: dict() of keywords and values. :rtype: dict[str,str|None] """ result = dict() query_string = query_string.strip('?') if query_string == '': return result try: for pair in query_string.split("&"): (k, v) = pair.split("=") result[k] = v # if the channelcode was empty, it was stripped, add it again. if keyword.CHANNEL_CODE not in result: Logger.debug( "Adding ChannelCode=None as it was missing from the dict: %s", result) result[keyword.CHANNEL_CODE] = None except: Logger.critical("Cannot determine query strings from %s", query_string, exc_info=True) raise return result def __str__(self): return "Plugin Params: {} ({})\n" \ "Handle: {}\n" \ "Name: {}\n" \ "Query: {}".format(self.params, len(self.params), self.handle, self.pluginName, self._params)
class Favourites: def __init__(self, path): """ Initializes a Favourites class that can be use to show, add and delete favourites. :param str path: The path to store the favourites file """ self.__filePattern = "%s-%s.xotfav" self.__pickler = Pickler() self.FavouriteFolder = path def add(self, channel, item, action_url): """ Adds a favourite for a specific channel. :param channel: The channel :param item: The mediaitem :param str action_url: The mediaitem's actionUrl """ Logger.debug("Adding item %s\nfor channel %s\n%s", item, channel, action_url) file_name = self.__filePattern % (channel.guid, item.guid) file_path = os.path.join(self.FavouriteFolder, file_name) pickle = self.__pickler.pickle_media_item(item) # Just double check for folder existence if not os.path.isdir(self.FavouriteFolder): os.makedirs(self.FavouriteFolder) # replacing to pickle in the actionUrl to save space action_url = self.__remove_pickle(action_url) try: with io.open(file_path, mode='w', encoding='utf-8') as file_handle: file_handle.write( "%s\n%s\n%s\n%s" % (channel.channelName, item.name, action_url, pickle)) except: Logger.error("Error saving favourite", exc_info=True) raise return # noinspection PyUnusedLocal def remove(self, item): """ Adds a favourite for a specific channel :param item: The mediaitem """ path_mask = os.path.join(self.FavouriteFolder, "*-%s.xotfav" % (item.guid, )) Logger.debug("Removing favourites for mask: %s", path_mask) for fav in glob.glob(path_mask): Logger.trace("Removing item %s\nFileName: %s", item, fav) os.remove(fav) return def list(self, channel=None): """ Lists favourites. If a channel was specified it will limit them to that. :param channel: The channel to limit the favourites to. :return: A list of tupples (action_url, pickle) :rtype: list """ favs = [] if channel: path_mask = os.path.join(self.FavouriteFolder, "%s-*.xotfav" % (channel.guid, )) else: path_mask = os.path.join(self.FavouriteFolder, "*.xotfav") Logger.debug("Fetching favourites for mask: %s", path_mask) for fav in glob.glob(path_mask): Logger.trace("Fetching %s", fav) try: with io.open(fav, mode='r', encoding='utf-8') as file_handle: channel_name = file_handle.readline().rstrip() name = file_handle.readline().rstrip() action_url = file_handle.readline().rstrip() if "pickle=" in action_url and "pickle=%s" not in action_url: # see issue https://github.com/retrospect-addon/plugin.video.retrospect/issues/1037 Logger.debug( "Found favourite with full pickle, removing the pickle as we should use the one from the file." ) action_url = self.__remove_pickle(action_url) pickle = file_handle.readline() except: Logger.error("Error fetching favourite", exc_info=True) raise if channel_name == "" or name == "" or action_url == "" or pickle == "": Logger.error( "Apparently the file had too few lines, corrupt Favourite, removing it:\n" "Pickle: %s\n" "Channel: %s\n" "Item: %s\n" "ActionUrl: %s\n" "Pickle: %s", fav, channel_name, name, action_url, pickle) # Remove the invalid favourite os.remove(fav) continue Logger.debug("Found favourite: %s", name) try: item = self.__pickler.de_pickle_media_item(pickle) except Exception: Logger.error("Cannot depickle item.", exc_info=True) # Let's not remove them for now. Just ignore. # os.remove(fav) continue validation_error = self.__pickler.validate( item, logger=Logger.instance()) if validation_error: Logger.error( "Invalid Pickled Item: %s\nRemoving favourite: %s", validation_error, fav) # Remove the invalid favourite os.remove(fav) continue # clean up the .: from titles if ".:" in item.name and ":." in item.name: item.name = item.name.strip(".:\0\b ") # add the channel name if channel is None: item.name = "%s [%s]" % (item.name, channel_name) item.clear_date() item.actionUrl = action_url % (pickle, ) favs.append(item) return favs def __remove_pickle(self, action_url): pickle = Regexer.do_regex("pickle=([^&]+)", action_url) if not pickle: return action_url return action_url.replace(pickle[0], "%s")