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

View File

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

View File

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