# Copyright (C) 2013-2015 # Sean Poyser (seanpoyser@gmail.com) # # This Program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # # This Program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with XBMC; see the file COPYING. If not, write to # the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. # http://www.gnu.org/copyleft/gpl.html # import xbmc import os import re import urllib import utils import sfile SHOWUNAVAIL = utils.ADDON.getSetting('SHOWUNAVAIL') == 'true' def getFavourites(file, limit=10000, validate=True, diamondSearch=False, chooser=False): import xbmcgui prefix = '' if not chooser: prefix = 'HOME:' if xbmcgui.getCurrentWindowId() == 10000 else '' xml = '' if sfile.exists(file): xml = sfile.read(file) items = [] faves = re.compile('').findall(xml) for fave in faves: fave = fave.replace('"', '&_quot_;') fave = fave.replace('\'', '"') fave = utils.unescape(fave) fave = fave.replace('name=""', '') try: name = re.compile('name="(.+?)"').findall(fave)[0] except: name = '' try: thumb = re.compile('thumb="(.+?)"').findall(fave)[0] except: thumb = '' try: cmd = fave.split('>', 1)[-1] except: cmd = '' #name = utils.Clean(name.replace( '&_quot_;', '"')) name = name.replace( '&_quot_;', '"') thumb = thumb.replace('&_quot_;', '"') cmd = cmd.replace( '&_quot_;', '"') add = False if diamondSearch: add = isValid(cmd) elif (SHOWUNAVAIL) or (not validate) or isValid(cmd): add = True if add: cmd = upgradeCmd(cmd) if cmd.startswith('PlayMedia'): option = 'mode' try: mode = int(favourite.getOption(cmd, option)) except: win = xbmcgui.getCurrentWindowId() cmd = updateSFOption(cmd, 'winID', win) name = resolve(name) cmd = patch(cmd) cmd = resolve(cmd) cmd = prefix + cmd items.append([name, thumb, cmd]) if len(items) > limit: return items return items def resolve(text): try: if '$LOCALIZE' in text: id = int(re.compile('\$LOCALIZE\[(.+?)\]').search(text).group(1)) text = text.replace('$LOCALIZE[%d]' % id, xbmc.getLocalizedString(id)) return resolve(text) if '$INFO' in text: str = re.compile('\$INFO\[(.+?)\]').search(text).group(1) text = text.replace('$INFO[%s]' % str, xbmc.getInfoLabel(str)) return resolve(text) except: pass return text def patch(cmd): cmd = cmd.replace('",return', 'SF_PATCHING1') cmd = cmd.replace('",return', 'SF_PATCHING2') cmd = cmd.replace(',return', '') cmd = cmd.replace('SF_PATCHING1' , '",return') cmd = cmd.replace('SF_PATCHING2' , '",return') return cmd def upgradeCmd(cmd): fanart = _getFanart(cmd) winID = _getWinID(cmd) cmd = _removeFanart(cmd) cmd = _removeWinID(cmd) options = {} if fanart: options['fanart'] = fanart if winID > -1: options['winID'] = winID if len(options) > 0: cmd = updateSFOptions(cmd, options) return cmd def writeFavourites(file, faves): kodiFile = os.path.join('special://profile', utils.FILENAME) isKodi = xbmc.translatePath(file) == xbmc.translatePath(kodiFile) f = sfile.file(file, 'w') f.write('') for fave in faves: try: name = utils.escape(fave[0]) thumb = utils.escape(fave[1]) cmd = utils.escape(fave[2]) if isKodi and cmd.lower().startswith('playmedia'): cmd = removeSFOptions(cmd) thumb = utils.convertToHome(thumb) name = 'name="%s" ' % name thumb = 'thumb="%s">' % thumb f.write('\n\t') except: pass f.write('\n') f.close() import xbmcgui try: count = int(xbmcgui.Window(10000).getProperty('diamond_Favourites_Count')) except: count = 0 xbmcgui.Window(10000).setProperty('diamond_Favourites_Count', str(count+1)) def tidy(cmd): cmd = cmd.replace('"', '') cmd = cmd.replace('&', '&') cmd = removeSFOptions(cmd) if cmd.startswith('RunScript'): cmd = cmd.replace('?content_type=', '&content_type=') cmd = re.sub('/&content_type=(.+?)"\)', '")', cmd) if cmd.endswith('/")'): cmd = cmd.replace('/")', '")') if cmd.endswith(')")'): cmd = cmd.replace(')")', ')') return cmd def isValid(cmd): if len(cmd) == 0: return False cmd = tidy(cmd) #if 'PlayMedia' in cmd: if cmd.startswith('PlayMedia'): return utils.verifyPlayMedia(cmd) #if 'RunScript' in cmd: if cmd.startswith('RunScript'): cmd = re.sub('/&content_type=(.+?)"\)', '")', cmd) if not utils.verifyScript(cmd): return False if 'plugin' in cmd: if not utils.verifyPlugin(cmd): return False return True def updateFave(file, update): cmd = update[2] fave, index, nFaves = findFave(file, cmd) removeFave(file, cmd) return insertFave(file, update, index) def replaceFave(file, update, oldCmd): fave, index, nFaves = findFave(file, oldCmd) if index < 0: return addFave(file, update) removeFave(file, oldCmd) return insertFave(file, update, index) def findFave(file, cmd): cmd = removeSFOptions(cmd) faves = getFavourites(file, validate=False) for idx, fave in enumerate(faves): if equals(fave[2], cmd): return fave, idx, len(faves) search = os.path.join(xbmc.translatePath(utils.ROOT), 'Search', utils.FILENAME).lower() if file.lower() != search: return None, -1, 0 for idx, fave in enumerate(faves): if '[%SF%]' in fave[2]: test = fave[2].split('[%SF%]', 1) if cmd.startswith(test[0]) and cmd.endswith(test[1]): return fave, idx, len(faves) if '[%SF+%]' in fave[2]: test = fave[2].split('[%SF+%]', 1) if cmd.startswith(test[0]) and cmd.endswith(test[1]): return fave, idx, len(faves) return None, -1, 0 def insertFave(file, newFave, index): copy = [] faves = getFavourites(file, validate=False) for fave in faves: if len(copy) == index: copy.append(newFave) copy.append(fave) if index >= len(copy): copy.append(newFave) writeFavourites(file, copy) return True def addFave(file, newFave): faves = getFavourites(file, validate=False) faves.append(newFave) writeFavourites(file, faves) return True def moveFave(src, dst, fave): if not copyFave(dst, fave): return False return removeFave(src, fave[2]) def copyFave(file, original): faves = getFavourites(file, validate=False) updated = False copy = list(original) copy = removeSFOptions(copy[2]) #if it is already in then just update it for idx, fave in enumerate(faves): if equals(removeSFOptions(fave[2]), copy): updated = True faves[idx] = original break if not updated: faves.append(original) writeFavourites(file, faves) return True def removeFave(file, cmd): cmd = removeSFOptions(cmd) copy = [] faves = getFavourites(file, validate=False) for fave in faves: if not equals(removeSFOptions(fave[2]), cmd): copy.append(fave) if len(copy) == len(faves): return False writeFavourites(file, copy) return True def _shiftUpIndex(index, max, faves): index -= 1 if index < 0: index = max cmd = faves[index][2] if isValid(cmd): return index return _shiftUpIndex(index, max, faves) def _shiftDownIndex(index, max, faves): index += 1 if index > max: index = 0 cmd = faves[index][2] if isValid(cmd): return index return _shiftDownIndex(index, max, faves) def shiftFave(file, cmd, up): faves = getFavourites(file, validate=True) if len(faves) < 2: return faves = getFavourites(file, validate=False) fave, index, nFaves = findFave(file, cmd) max = nFaves - 1 if up: index = _shiftUpIndex(index, max, faves) else: index = _shiftDownIndex(index, max, faves) removeFave(file, cmd) return insertFave(file, fave, index) def renameFave(file, cmd, newName): copy = [] faves = getFavourites(file, validate=False) for fave in faves: if equals(fave[2], cmd): fave[0] = newName copy.append(fave) writeFavourites(file, copy) return True def equals(fave, cmd): fave = fave.strip() cmd = cmd.strip() if fave == cmd: return True fave = removeSFOptions(fave) cmd = removeSFOptions(cmd) if fave == cmd: return True if fave == cmd.replace('")', '/")'): return True if '[%SF%]' in fave: test = fave.split('[%SF%]', 1) if cmd.startswith(test[0]) and cmd.endswith(test[1]): return True if '[%SF+%]' in fave: test = fave.split('[%SF+%]', 1) if cmd.startswith(test[0]) and cmd.endswith(test[1]): return True return False def addFanart(cmd, fanart): if len(fanart) < 1: return cmd return updateSFOption(cmd, 'fanart', utils.convertToHome(fanart)) def updateSFOption(cmd, option, value): options = getSFOptions(cmd) options[option] = value return updateSFOptions(cmd, options) def updateSFOptions(cmd, options): cmd = removeSFOptions(cmd) if len(options) == 0: return cmd hasReturn = False if cmd.endswith(',return)'): hasReturn = True cmd = cmd.replace(',return', '') if cmd.endswith('")'): cmd = cmd.rsplit('")', 1)[0] suffix = '?' if '?' in cmd: suffix = '&' values = '' for key in options.keys(): value = str(options[key]) if len(value) > 0: values += '%s=%s&' % (key, value) if len(values) > 0: cmd += suffix + 'sf_options=%s_options_sf"' % urllib.quote_plus(values) else: cmd += '"' if hasReturn: cmd += ',return)' else: cmd += ')' return cmd def getSFOptions(cmd): try: options = urllib.unquote_plus(re.compile('sf_options=(.+?)_options_sf').search(cmd).group(1)) except: return {} params = get_params(options) return params def removeSFOptions(cmd): if 'sf_options=' not in cmd: return cmd cmd = cmd.replace('?sf_options=', '&sf_options=') cmd = re.sub('&sf_options=(.+?)_options_sf"\)', '")', cmd) cmd = re.sub('&sf_options=(.+?)_options_sf",return\)', '",return)', cmd) cmd = re.sub('&sf_options=(.+?)_options_sf', '', cmd) #cmd = cmd.replace('/")', '")') return cmd def getFanart(cmd): return getOption(cmd, 'fanart') def getOption(cmd, option): options = getSFOptions(cmd) try: return options[option] except: return '' def get_params(path): params = {} #path = path.split('?', 1)[-1] pairs = path.split('&') for pair in pairs: split = pair.split('=') if len(split) > 1: #params[split[0]] = urllib.unquote_plus(split[1]) params[split[0]] = split[1] return params #used only during upgrade process def _removeFanart(cmd): if 'sf_fanart=' not in cmd: return cmd cmd = cmd.replace('?sf_fanart=', '&sf_fanart=') cmd = cmd.replace('&sf_fanart=', '&sf_fanart=X') #in case no fanart cmd = re.sub('&sf_fanart=(.+?)_"\)', '")', cmd) cmd = re.sub('&sf_fanart=(.+?)_",return\)', '",return)', cmd) cmd = re.sub('&sf_fanart=(.+?)_', '', cmd) cmd = cmd.replace('/")', '")') return cmd #used only during upgrade process def _getFanart(cmd): cmd = cmd.replace(',return', '') try: return urllib.unquote_plus(re.compile('sf_fanart=(.+?)_"\)').search(cmd).group(1)) except: pass cmd = urllib.unquote_plus(cmd) cmd = cmd.replace(',return', '') try: return urllib.unquote_plus(re.compile('sf_fanart=(.+?)_"\)').search(cmd).group(1)) except: pass return '' #used only during upgrade process def _removeWinID(cmd): if 'sf_win_id' not in cmd: return cmd cmd = cmd.replace('?sf_win_id=', '&sf_win_id=') cmd = cmd.replace('&sf_win_id=', '&sf_win_id=X') #in case no win_id cmd = re.sub('&sf_win_id=(.+?)_"\)', '")', cmd) return cmd #used only during upgrade process def _getWinID(cmd): if 'sf_win_id' not in cmd: return -1 try: return int(re.compile('sf_win_id=(.+?)_').search(cmd).group(1)) except: pass return -1