diff --git a/default.py b/default.py index d60cf55..bb1a04c 100644 --- a/default.py +++ b/default.py @@ -4,6 +4,7 @@ import xbmcgui import resources.lib.utils as utils from resources.lib.backup import XbmcBackup + def get_params(): param = {} try: @@ -19,6 +20,7 @@ def get_params(): return param + # the program mode mode = -1 params = get_params() @@ -30,6 +32,7 @@ if("mode" in params): elif(params['mode'] == 'restore'): mode = 1 + # if mode wasn't passed in as arg, get from user if(mode == -1): # by default, Backup,Restore,Open Settings diff --git a/launcher.py b/launcher.py index ff0660a..f7b5ce4 100644 --- a/launcher.py +++ b/launcher.py @@ -1,3 +1,4 @@ +# launcher for various helpful functions found in the settings.xml area import sys import xbmc import xbmcgui @@ -6,7 +7,6 @@ import resources.lib.utils as utils from resources.lib.authorizers import DropboxAuthorizer from resources.lib.advanced_editor import AdvancedBackupEditor -# launcher for various helpful functions found in the settings.xml area def authorize_cloud(cloudProvider): # drobpox @@ -18,15 +18,17 @@ def authorize_cloud(cloudProvider): else: xbmcgui.Dialog().ok(utils.getString(30010), utils.getString(30107) + ' ' + utils.getString(30027)) + def remove_auth(): # triggered from settings.xml - asks if user wants to delete OAuth token information shouldDelete = xbmcgui.Dialog().yesno(utils.getString(30093), utils.getString(30094), utils.getString(30095), autoclose=7000) if(shouldDelete): # delete any of the known token file types - xbmcvfs.delete(xbmc.translatePath(utils.data_dir() + "tokens.txt")) # dropbox - xbmcvfs.delete(xbmc.translatePath(utils.data_dir() + "google_drive.dat")) # google drive - + xbmcvfs.delete(xbmc.translatePath(utils.data_dir() + "tokens.txt")) # dropbox + xbmcvfs.delete(xbmc.translatePath(utils.data_dir() + "google_drive.dat")) # google drive + + def get_params(): param = {} try: @@ -34,7 +36,7 @@ def get_params(): args = i if('=' in args): if(args.startswith('?')): - args = args[1:] # legacy in case of url params + args = args[1:] # legacy in case of url params splitString = args.split('=') param[splitString[0]] = splitString[1] except: @@ -42,6 +44,7 @@ def get_params(): return param + params = get_params() if(params['action'] == 'authorize_cloud'): diff --git a/resources/lib/extractor.py b/resources/lib/extractor.py index b490e27..f49b430 100644 --- a/resources/lib/extractor.py +++ b/resources/lib/extractor.py @@ -1,11 +1,12 @@ from . import utils as utils + class ZipExtractor: def extract(self, zipFile, outLoc, progressBar): utils.log("extracting zip archive") - result = True # result is true unless we fail + result = True # result is true unless we fail # update the progress bar progressBar.updateProgress(0, utils.getString(30100)) diff --git a/resources/lib/progressbar.py b/resources/lib/progressbar.py index 5a75eb4..baafb81 100644 --- a/resources/lib/progressbar.py +++ b/resources/lib/progressbar.py @@ -1,6 +1,7 @@ import xbmcgui from . import utils as utils + class BackupProgressBar: NONE = 2 DIALOG = 0 @@ -31,7 +32,7 @@ class BackupProgressBar: # update the progress bar if(self.mode != self.NONE): - if(message != None): + if(message is not None): # need different calls for dialog and background bars if(self.mode == self.DIALOG): self.progressBar.update(percent, message) diff --git a/resources/lib/tinyurl.py b/resources/lib/tinyurl.py index ac892b8..7f82053 100644 --- a/resources/lib/tinyurl.py +++ b/resources/lib/tinyurl.py @@ -1,7 +1,8 @@ -from future.moves.urllib.request import urlopen - # this is duplicated in snipppets of code from all over the web, credit to no one # in particular - to all those that have gone before me! +from future.moves.urllib.request import urlopen + + def shorten(aUrl): tinyurl = 'http://tinyurl.com/api-create.php?url=' req = urlopen(tinyurl + aUrl) diff --git a/resources/lib/utils.py b/resources/lib/utils.py index 8b0409e..490cbb1 100644 --- a/resources/lib/utils.py +++ b/resources/lib/utils.py @@ -5,30 +5,39 @@ import xbmcaddon __addon_id__= 'script.xbmcbackup' __Addon = xbmcaddon.Addon(__addon_id__) + def data_dir(): return __Addon.getAddonInfo('profile') + def addon_dir(): return __Addon.getAddonInfo('path') + def openSettings(): __Addon.openSettings() + def log(message, loglevel=xbmc.LOGDEBUG): - xbmc.log(__addon_id__ + "-" + __Addon.getAddonInfo('version') + ": " + message, level=loglevel) + xbmc.log(__addon_id__ + "-" + __Addon.getAddonInfo('version') + ": " + message, level=loglevel) + def showNotification(message): xbmcgui.Dialog().notification(getString(30010), message, time=4000, icon=xbmc.translatePath(__Addon.getAddonInfo('path') + "/resources/images/icon.png")) + def getSetting(name): return __Addon.getSetting(name) + def setSetting(name, value): __Addon.setSetting(name, value) - + + def getString(string_id): return __Addon.getLocalizedString(string_id) + def getRegionalTimestamp(date_time, dateformat=['dateshort']): result = '' diff --git a/resources/lib/vfs.py b/resources/lib/vfs.py index 8878728..b0bf61e 100644 --- a/resources/lib/vfs.py +++ b/resources/lib/vfs.py @@ -10,6 +10,7 @@ from . import utils as utils from .dropbox.files import WriteMode, CommitInfo, UploadSessionCursor from . authorizers import DropboxAuthorizer + class Vfs: root_path = None @@ -54,6 +55,7 @@ class Vfs: def cleanup(self): return True + class XBMCFileSystem(Vfs): def listdir(self, directory): @@ -77,6 +79,7 @@ class XBMCFileSystem(Vfs): def exists(self, aFile): return xbmcvfs.exists(aFile) + class ZipFileSystem(Vfs): zip = None @@ -115,8 +118,9 @@ class ZipFileSystem(Vfs): def listFiles(self): return self.zip.infolist() + class DropboxFileSystem(Vfs): - MAX_CHUNK = 50 * 1000 * 1000 # dropbox uses 150, reduced to 50 for small mem systems + MAX_CHUNK = 50 * 1000 * 1000 # dropbox uses 150, reduced to 50 for small mem systems client = None APP_KEY = '' APP_SECRET = '' @@ -136,7 +140,7 @@ class DropboxFileSystem(Vfs): def listdir(self, directory): directory = self._fix_slashes(directory) - if(self.client != None and self.exists(directory)): + if(self.client is not None and self.exists(directory)): files = [] dirs = [] metadata = self.client.files_list_folder(directory) @@ -153,7 +157,7 @@ class DropboxFileSystem(Vfs): def mkdir(self, directory): directory = self._fix_slashes(directory) - if(self.client != None): + if(self.client is not None): # sort of odd but always return true, folder create is implicit with file upload return True else: @@ -161,7 +165,7 @@ class DropboxFileSystem(Vfs): def rmdir(self, directory): directory = self._fix_slashes(directory) - if(self.client != None and self.exists(directory)): + if(self.client is not None and self.exists(directory)): # dropbox is stupid and will refuse to do this sometimes, need to delete recursively dirs, files = self.listdir(directory) @@ -178,7 +182,7 @@ class DropboxFileSystem(Vfs): def rmfile(self, aFile): aFile = self._fix_slashes(aFile) - if(self.client != None and self.exists(aFile)): + if(self.client is not None and self.exists(aFile)): self.client.files_delete(aFile) return True else: @@ -187,13 +191,13 @@ class DropboxFileSystem(Vfs): def exists(self, aFile): aFile = self._fix_slashes(aFile) - if(self.client != None): + if(self.client is not None): # can't list root metadata if(aFile == ''): return True try: - meta_data = self.client.files_get_metadata(aFile) + self.client.files_get_metadata(aFile) # if we make it here the file does exist return True except: @@ -204,7 +208,7 @@ class DropboxFileSystem(Vfs): def put(self, source, dest, retry=True): dest = self._fix_slashes(dest) - if(self.client != None): + if(self.client is not None): # open the file and get its size f = open(source, 'rb') f_size = os.path.getsize(source) @@ -212,7 +216,7 @@ class DropboxFileSystem(Vfs): try: if(f_size < self.MAX_CHUNK): # use the regular upload - response = self.client.files_upload(f.read(), dest, mode=WriteMode('overwrite')) + self.client.files_upload(f.read(), dest, mode=WriteMode('overwrite')) else: # start the upload session upload_session = self.client.files_upload_session_start(f.read(self.MAX_CHUNK)) @@ -228,7 +232,7 @@ class DropboxFileSystem(Vfs): self.client.files_upload_session_append_v2(f.read(self.MAX_CHUNK), upload_cursor) upload_cursor.offset = f.tell() - # if no errors we're good! + # if no errors we're good! return True except Exception as anError: utils.log(str(anError)) @@ -243,9 +247,9 @@ class DropboxFileSystem(Vfs): return False def get_file(self, source, dest): - if(self.client != None): + if(self.client is not None): # write the file locally - f = self.client.files_download_to_file(dest, source) + self.client.files_download_to_file(dest, source) return True else: return False diff --git a/scheduler.py b/scheduler.py index d6cfe49..e3dc2c0 100644 --- a/scheduler.py +++ b/scheduler.py @@ -9,6 +9,7 @@ from resources.lib.backup import XbmcBackup UPGRADE_INT = 2 # to keep track of any upgrade notifications + class BackupScheduler: monitor = None enabled = "false" @@ -17,7 +18,7 @@ class BackupScheduler: restore_point = None def __init__(self): - self.monitor = UpdateMonitor(update_method = self.settingsChanged) + self.monitor = UpdateMonitor(update_method=self.settingsChanged) self.enabled = utils.getSetting("enable_scheduler") self.next_run_path = xbmc.translatePath(utils.data_dir()) + 'next_run.txt' @@ -42,12 +43,12 @@ class BackupScheduler: if(0 < nr <= time.time() and utils.getSetting('schedule_miss') == 'true'): utils.log("scheduled backup was missed, doing it now...") progress_mode = int(utils.getSetting('progress_mode')) - + if(progress_mode == 0): - progress_mode = 1 # Kodi just started, don't block it with a foreground progress bar + progress_mode = 1 # Kodi just started, don't block it with a foreground progress bar self.doScheduledBackup(progress_mode) - + self.setup() def setup(self): @@ -104,7 +105,7 @@ class BackupScheduler: if(backup.remoteConfigured()): - if(int(utils.getSetting('progress_mode')) in [0,1]): + if(int(utils.getSetting('progress_mode')) in [0, 1]): backup.backup(True) else: backup.backup(False) @@ -136,7 +137,7 @@ class BackupScheduler: fh.close() # only show when not in silent mode - if(progress_mode != 2): + if(progress_mode != 2): utils.showNotification(utils.getString(30081) + " " + utils.getRegionalTimestamp(datetime.fromtimestamp(self.next_run), ['dateshort', 'time'])) def settingsChanged(self): @@ -184,6 +185,7 @@ class BackupScheduler: return shouldContinue + class UpdateMonitor(xbmc.Monitor): update_method = None @@ -194,4 +196,5 @@ class UpdateMonitor(xbmc.Monitor): def onSettingsChanged(self): self.update_method() + BackupScheduler().start()