Merge branch 'master' into krypton

This commit is contained in:
Rob Weber 2019-09-11 10:05:16 -05:00
commit b21c11de26
4 changed files with 58 additions and 80 deletions

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<addon id="script.xbmcbackup"
name="Backup" version="1.5.0" provider-name="robweber">
name="Backup" version="1.5.1" provider-name="robweber">
<requires>
<!-- jarvis -->
<import addon="xbmc.python" version="2.25.0"/>
@ -95,10 +95,8 @@
<screenshot>resources/images/screenshot3.png</screenshot>
<screenshot>resources/images/screenshot4.png</screenshot>
</assets>
<news>Version 1.1.4
- added file chunk support for dropbox uploads
- fixed settings duplicate ids, thanks aster-anto
- added scheduler delay to assist with time sync (rpi mostly)
<news>Version 1.5.1
- fix guisettings restores not working - thanks Bluerayx
</news>
</extension>
</addon>

View File

@ -1,3 +1,7 @@
Version 1.5.1
fix guisettings restores not working - thanks Bluerayx
Version 1.5.0
Overhaul of file selection and restore procedures. Breaking Change with previous versions PR117

View File

@ -4,12 +4,12 @@ import xbmcvfs
import utils as utils
import time
import json
import os
from datetime import datetime
from vfs import XBMCFileSystem,DropboxFileSystem,ZipFileSystem,GoogleDriveFilesystem
from progressbar import BackupProgressBar
from resources.lib.guisettings import GuiSettingsManager
from resources.lib.extractor import ZipExtractor
from __builtin__ import file
def folderSort(aKey):
result = aKey[0]
@ -321,10 +321,10 @@ class XbmcBackup:
self.xbmc_vfs.rmfile(xbmc.translatePath("special://temp/" + self.restore_point))
self.xbmc_vfs.rmdir(self.remote_vfs.root_path)
if(utils.getSetting("backup_config") == "true"):
#update the guisettings information (or what we can from it)
gui_settings = GuiSettingsManager('special://home/userdata/guisettings.xml')
gui_settings.run()
#update the guisettings information (or what we can from it)
gui_settings = GuiSettingsManager()
gui_settings.run()
#call update addons to refresh everything
xbmc.executebuiltin('UpdateLocalAddons')
@ -398,13 +398,15 @@ class XbmcBackup:
dest.mkdir(dest.root_path + aFile[len(source.root_path) + 1:])
else:
self._updateProgress()
wroteFile = True
destFile = dest.root_path + aFile[len(source.root_path):]
if(isinstance(source,DropboxFileSystem) or isinstance(source,GoogleDriveFilesystem)):
#if copying from cloud storage we need the file handle, use get_file
wroteFile = source.get_file(aFile,dest.root_path + aFile[len(source.root_path):])
wroteFile = source.get_file(aFile,destFile)
else:
#copy using normal method
wroteFile = dest.put(aFile,dest.root_path + aFile[len(source.root_path):])
wroteFile = dest.put(aFile,destFile)
#if result is still true but this file failed
if(not wroteFile and result):
@ -555,13 +557,13 @@ class FileManager:
if(directory[-1:] == '/' or directory[-1:] == '\\'):
directory = directory[:-1]
if(self.vfs.exists(directory + "/")):
if(self.vfs.exists(directory + os.path.sep)):
dirs,files = self.vfs.listdir(directory)
if(recurse):
#create all the subdirs first
for aDir in dirs:
dirPath = xbmc.validatePath(xbmc.translatePath(directory + "/" + aDir))
dirPath = xbmc.validatePath(xbmc.translatePath(directory + os.path.sep + aDir))
file_ext = aDir.split('.')[-1]
#check if directory is excluded
@ -581,7 +583,7 @@ class FileManager:
#copy all the files
for aFile in files:
filePath = xbmc.translatePath(directory + "/" + aFile)
filePath = xbmc.translatePath(directory + os.path.sep + aFile)
self.addFile(filePath)
def addDir(self,dirMeta):

View File

@ -6,94 +6,68 @@ import xbmc,xbmcvfs
class GuiSettingsManager:
settingsFile = None
doc = None
settings_allowed = list()
found_settings = list()
def __init__(self,settingsFile):
self._readFile(xbmc.translatePath(settingsFile))
def __init__(self):
#first make a copy of the file
xbmcvfs.copy(xbmc.translatePath('special://home/userdata/guisettings.xml'), xbmc.translatePath("special://home/userdata/guisettings.xml.restored"))
#read in the copy
self._readFile(xbmc.translatePath('special://home/userdata/guisettings.xml.restored'))
def run(self):
#get a list of all the settings we can manipulate via json
json_response = json.loads(xbmc.executeJSONRPC('{"jsonrpc":"2.0", "id":1, "method":"Settings.GetSettings","params":{"level":"advanced"}}'))
settings = json_response['result']['settings']
for aSetting in settings:
self.settings_allowed.append(aSetting['id'])
#parse the existing xml file and get all the settings
root_nodes = self.__parseNodes(self.doc.documentElement)
currentSettings = {}
for aNode in root_nodes:
secondary_list = self.__parseNodes(self.doc.getElementsByTagName(aNode.name)[0])
for aSetting in settings:
if('value' in aSetting):
currentSettings[aSetting['id']] = aSetting['value']
for secondNode in secondary_list:
#if the node does not have children and is not default
if(not secondNode.hasChildren and not secondNode.isDefault):
if(secondNode.json_name() in self.settings_allowed):
self.found_settings.append(secondNode)
#parse the existing xml file and get all the settings we need to restore
restoreSettings = self.__parseNodes(self.doc.getElementsByTagName('setting'))
#get a list where the restore setting value != the current value
updateSettings = {k: v for k, v in restoreSettings.items() if (k in currentSettings and currentSettings[k] != v)}
#go through all the found settings and update them
for aSetting in self.found_settings:
utils.log("updating: " + aSetting.json_name() + ", value: " + aSetting.value)
jsonObj = {"jsonrpc":"2.0","id":1,"method":"Settings.SetSettingValue","params":{"setting":"","value":""}}
for anId, aValue in updateSettings.items():
utils.log("updating: " + anId + ", value: " + str(aValue))
jsonObj['params']['setting'] = anId
jsonObj['params']['value'] = aValue
#check for boolean and numeric values
if(aSetting.value.isdigit() or (aSetting.value == 'true' or aSetting.value == 'false')):
xbmc.executeJSONRPC('{"jsonrpc":"2.0", "id":1, "method":"Settings.SetSettingValue","params":{"setting":"' + aSetting.json_name() + '","value":' + aSetting.value + '}}')
else:
xbmc.executeJSONRPC('{"jsonrpc":"2.0", "id":1, "method":"Settings.SetSettingValue","params":{"setting":"' + aSetting.json_name() + '","value":"' + utils.encode(aSetting.value) + '"}}')
#make a copy of the guisettings file to make user based restores easier
xbmcvfs.copy(self.settingsFile, xbmc.translatePath("special://home/userdata/guisettings.xml.restored"))
xbmc.executeJSONRPC(json.dumps(jsonObj))
def __parseNodes(self,nodeList):
result = []
result = {}
for node in nodeList.childNodes:
if(node.nodeType == self.doc.ELEMENT_NODE):
aSetting = SettingNode(node.nodeName)
#detect if there are any element nodes
if(len(node.childNodes) > 0):
for child_node in node.childNodes:
if(child_node.nodeType == self.doc.ELEMENT_NODE):
aSetting.hasChildren = True
if(not aSetting.hasChildren and len(node.childNodes) > 0):
aSetting.value = node.firstChild.nodeValue
if('default' not in node.attributes.keys()):
aSetting.isDefault = False
aSetting.parent = node.parentNode.nodeName
result.append(aSetting)
for node in nodeList:
nodeValue = ''
if(node.firstChild != None):
nodeValue = node.firstChild.nodeValue
#check for numbers and booleans
if(nodeValue.isdigit()):
nodeValue = int(nodeValue)
elif(nodeValue == 'true'):
nodeValue = True
elif(nodeValue == 'false'):
nodeValue = False
result[node.getAttribute('id')] = nodeValue
return result
def _readFile(self,fileLoc):
if(xbmcvfs.exists(fileLoc)):
try:
self.doc = minidom.parse(fileLoc)
self.settingsFile = fileLoc
except ExpatError:
utils.log("Can't read " + fileLoc)
class SettingNode:
name = ''
value = ''
hasChildren = False
isDefault = True
parent = ''
def __init__(self,name):
self.name = name
def json_name(self):
return self.parent + "." + self.name