Compare commits

...

17 Commits

Author SHA1 Message Date
Rob Weber 6a9f65318f updated changelog 2025-12-31 14:21:59 -06:00
Rob Weber 6adceb3060 version bump 2025-12-31 14:16:09 -06:00
Rob Weber eb52649eb8 fix bug with settings restore #248 2025-12-31 14:10:23 -06:00
Rob Weber 1dcc302ddd part of #247 2025-11-05 15:10:49 -06:00
robweber 1559df4d4c version 1.7.1 2024-08-17 11:03:32 -05:00
Rob Weber dd2ddb50be updated changelog 2024-06-13 18:07:23 -05:00
robweber 4f00c1d983 change version 2024-04-28 10:43:35 -05:00
robweber ca7f6e89c7 updated changelog 2024-04-28 10:40:00 -05:00
robweber 7e820c9ad7 part of #230 2024-04-28 10:35:24 -05:00
robweber 324f3a46cf fixes #235 2024-04-28 10:22:31 -05:00
robweber d1907baf38 updated changelog.md 2024-04-28 10:12:12 -05:00
rjclark99 a32e6f2656 Enhanced self.APP_KEY and self.APP_SECRET grabbing. (#233)
* added function getSettingStringStripped to utils and implemented in authorizers.py dropbox  flow line 47

* added function getSettingStringStripped to utils and implemented in authorizers.py dropbox  flow line 47
2024-04-28 10:09:59 -05:00
Rob Weber ca10bf7307 version bump 2024-04-17 11:43:24 -05:00
Rob Weber dc88c2615a updated news 2024-04-17 11:42:38 -05:00
Rob Weber 090842b03c prompt to close Kodi when restore completes
closes #228
2024-01-25 09:13:02 -06:00
Rob Weber f6fae17c19 updated changelog.md 2024-01-25 08:46:12 -06:00
Rob Weber 780f0f8401 added dict key to designate files instead of '-' sign 2024-01-24 15:42:07 -06:00
7 changed files with 71 additions and 21 deletions
+4 -6
View File
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<addon id="script.xbmcbackup"
name="Backup" version="1.7.0~beta2" provider-name="robweber">
name="Backup" version="1.7.2" provider-name="robweber">
<requires>
<import addon="xbmc.python" version="3.0.0"/>
<import addon="script.module.dateutil" version="2.8.0" />
@@ -24,11 +24,9 @@
<screenshot>resources/images/screenshot3.jpg</screenshot>
<screenshot>resources/images/screenshot4.jpg</screenshot>
</assets>
<news>Version 1.7.0
Can add suffix to backup folder names
translations sync
Minor UI fixes
Fixed Dropbox tokens expiring by using refresh tokens
<news>Version 1.7.2
Fix bug with gui settings restore
strptime Python bugfix
</news>
<summary lang="ar_SA">إنسخ إحتياطياً قاعده بيانات إكس بى إم سى وملفات اﻹعدادات فى حاله وقوع إنهيار مع إمكانيه اﻹسترجاع</summary>
<summary lang="bg_BG">Добавката може да създава резервни копия и възстановява базата данни и настройките на Kodi, в случай на срив или повреда на файловете.</summary>
+25 -1
View File
@@ -4,12 +4,35 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
## Unreleased
## [Version 1.7.2](https://github.com/robweber/xbmcbackup/compare/matrix-1.7.1...robweber:matrix-1.7.2)
### Fixed
- fixed a bug with the GUI settings restore, the settings key was not identified properly. Thanks @alexhass
- implemented [suggested fix](https://kodi.wiki/view/Python_Problems#datetime.strptime) for strptime Python bug
## [Version 1.7.1](https://github.com/robweber/xbmcbackup/compare/matrix-1.7.0...robweber:matrix-1.7.1)
### Added
- `utils.getSettingStripped` to trim whitespace around setting strings
### Changed
- Dropbox Secret and App Key are trimmed on loading - thanks @rjclark99
- added additional dialog information when gathering files for a Restore. This doesn't fix the speed which these happen since that is related to the platform but does provide more info that it's working.
### Fixed
- issue where Zip file restores were failing due to a missing `is_dir` attribute
## [Version 1.7.0](https://github.com/robweber/xbmcbackup/compare/matrix-1.6.8...robweber:matrix-1.7.0)
### Added
- You can now append a suffix to the end of each backup name (folder or zip file). This is only available in the Advanced or Expert settings.
- validation file now saves a list of all installed addons and versions
- prompt to close Kodi at the end of successful restore
### Changed
@@ -17,6 +40,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
- modified GitHub issue template slightly
- translations sync
- token files are stored in a `.json` instead of a `.txt` file
- file discovery process now flags directories with an `is_dir` metadata property instead of prefixing with a dash (-). This was done for legacy reasons and there is no reason for it.
### Fixed
@@ -294,7 +294,7 @@ msgid "Restart Kodi"
msgstr ""
msgctxt "#30078"
msgid "You should restart Kodi to continue"
msgid "A restart is recommended, select Yes to close Kodi"
msgstr ""
msgctxt "#30079"
@@ -629,3 +629,11 @@ msgstr ""
msgctxt "#30161"
msgid "Amend a string to the end of each backup folder or ZIP file"
msgstr ""
msgctxt "#30162"
msgid "this could take some time"
msgstr ""
msgctxt "#30163"
msgid "Current folder"
msgstr ""
+13 -4
View File
@@ -2,9 +2,10 @@ import xbmcgui
import xbmcvfs
import json
import pyqrcode
import time
import resources.lib.tinyurl as tinyurl
import resources.lib.utils as utils
from datetime import datetime
import datetime
# don't die on import error yet, these might not even get used
try:
@@ -13,6 +14,14 @@ try:
except ImportError:
pass
# fix for datetime.strptime bug https://kodi.wiki/view/Python_Problems#datetime.strptime
class proxydt(datetime.datetime):
@classmethod
def strptime(cls, date_string, format):
return datetime.datetime(*(time.strptime(date_string, format)[:6]))
datetime.datetime = proxydt
class QRCode(xbmcgui.WindowXMLDialog):
def __init__(self, *args, **kwargs):
@@ -44,8 +53,8 @@ class DropboxAuthorizer:
APP_SECRET = ""
def __init__(self):
self.APP_KEY = utils.getSetting('dropbox_key')
self.APP_SECRET = utils.getSetting('dropbox_secret')
self.APP_KEY = utils.getSettingStringStripped('dropbox_key')
self.APP_SECRET = utils.getSettingStringStripped('dropbox_secret')
def setup(self):
result = True
@@ -145,7 +154,7 @@ class DropboxAuthorizer:
if(token.strip() != ""):
result = json.loads(token)
# convert expiration back to a datetime object
result['expiration'] = datetime.strptime(result['expiration'], "%Y-%m-%d %H:%M:%S.%f")
result['expiration'] = datetime.datetime.strptime(result['expiration'], "%Y-%m-%d %H:%M:%S.%f")
token_file.close()
+17 -8
View File
@@ -228,7 +228,7 @@ class XbmcBackup:
# copy just this file from the remote vfs
self.transferSize = self.remote_vfs.fileSize(self.remote_base_path + self.restore_point)
zipFile = []
zipFile.append({'file': self.remote_base_path + self.restore_point, 'size': self.transferSize})
zipFile.append({'file': self.remote_base_path + self.restore_point, 'size': self.transferSize, 'is_dir': False})
# set transfer size
self.transferLeft = self.transferSize
@@ -285,7 +285,9 @@ class XbmcBackup:
self._createResumeBackupFile()
# do not continue running
xbmcgui.Dialog().ok(utils.getString(30077), utils.getString(30078))
if(xbmcgui.Dialog().yesno(utils.getString(30077), utils.getString(30078), autoclose=15000)):
xbmc.executebuiltin('Quit')
return
# check if settings should be restored from this backup
@@ -314,6 +316,7 @@ class XbmcBackup:
self.xbmc_vfs.set_root(xbmcvfs.translatePath(aDir['path']))
if(self.remote_vfs.exists(self.remote_vfs.root_path + aDir['name'] + '/')):
# walk the directory
self.progressBar.updateProgress(0, f"{utils.getString(30049)}....{utils.getString(30162)}\n{utils.getString(30163)}: {aDir['name']}")
fileManager.walkTree(self.remote_vfs.root_path + aDir['name'] + '/')
self.transferSize = self.transferSize + fileManager.fileSize()
@@ -347,6 +350,11 @@ class XbmcBackup:
# call update addons to refresh everything
xbmc.executebuiltin('UpdateLocalAddons')
# notify user that restart is recommended
if(xbmcgui.Dialog().yesno(utils.getString(30077), utils.getString(30078), autoclose=15000)):
xbmc.executebuiltin('Quit')
def _setupVFS(self, mode=-1, progressOverride=False):
# set windows setting to true
window = xbmcgui.Window(10000)
@@ -414,9 +422,9 @@ class XbmcBackup:
if(utils.getSettingBool('verbose_logging')):
utils.log('Writing file: ' + aFile['file'])
if(aFile['file'].startswith("-")):
if(aFile['is_dir']):
self._updateProgress('%s remaining\nwriting %s' % (utils.diskString(self.transferLeft), os.path.basename(aFile['file'][len(source.root_path):]) + "/"))
dest.mkdir(dest.root_path + aFile['file'][len(source.root_path) + 1:])
dest.mkdir(dest.root_path + aFile['file'][len(source.root_path):])
else:
self._updateProgress('%s remaining\nwriting %s' % (utils.diskString(self.transferLeft), os.path.basename(aFile['file'][len(source.root_path):])))
self.transferLeft = self.transferLeft - aFile['size']
@@ -426,6 +434,7 @@ class XbmcBackup:
# if result is still true but this file failed
if(not wroteFile and result):
utils.log("Failed to write " + aFile['file'])
result = False
return result
@@ -583,7 +592,7 @@ class FileManager:
def walk(self):
for aDir in self.root_dirs:
self.addFile('-' + xbmcvfs.translatePath(aDir['path']))
self.addFile(xbmcvfs.translatePath(aDir['path']), True)
self.walkTree(xbmcvfs.translatePath(aDir['path']), aDir['recurse'])
def walkTree(self, directory, recurse=True):
@@ -605,7 +614,7 @@ class FileManager:
# check if directory is excluded
if(not any(dirPath.startswith(exDir) for exDir in self.exclude_dir)):
self.addFile("-" + dirPath)
self.addFile(dirPath, True)
# catch for "non directory" type files
shouldWalk = True
@@ -628,7 +637,7 @@ class FileManager:
else:
self.excludeFile(xbmcvfs.translatePath(dirMeta['path']))
def addFile(self, filename):
def addFile(self, filename, is_dir = False):
# write the full remote path name of this file
if(utils.getSettingBool('verbose_logging')):
utils.log("Add File: " + filename)
@@ -637,7 +646,7 @@ class FileManager:
fSize = self.vfs.fileSize(filename)
self.totalSize = self.totalSize + fSize
self.fileArray.append({'file': filename, 'size': fSize})
self.fileArray.append({'file': filename, 'size': fSize, 'is_dir': is_dir})
def excludeFile(self, filename):
# remove trailing slash
+1 -1
View File
@@ -40,7 +40,7 @@ class GuiSettingsManager:
restoreCount = 0
for aSetting in restoreSettings:
# Ensure key exists before referencing
if(aSetting['id'] in settingsDict.values()):
if(aSetting['id'] in settingsDict.keys()):
# only update a setting if its different than the current (action types have no value)
if(aSetting['type'] != 'action' and settingsDict[aSetting['id']] != aSetting['value']):
if(utils.getSettingBool('verbose_logging')):
+2
View File
@@ -30,6 +30,8 @@ def showNotification(message):
def getSetting(name):
return __Addon.getSetting(name)
def getSettingStringStripped(name):
return __Addon.getSettingString(name).strip()
def getSettingBool(name):
return bool(__Addon.getSettingBool(name))