diff --git a/addon.xml b/addon.xml index 3d1d5ee..0e9a9db 100644 --- a/addon.xml +++ b/addon.xml @@ -1,5 +1,5 @@ - + @@ -19,5 +19,32 @@ icon.png fanart.png + +2023.01.09.0 + - Added AutoClean Cache functionality every x days at a given hour. + - Backup always replaced the home folder reference in xml files with special://home + Not all addons can handle this replace so it is now possible via a setting to disable this. + - Backup Cancel didn't work. This is now fixed. + +2023.01.01.0 + - Fix a fix on 2022.12.28.0 + +2022.12.28.0 + - Fix crash with full backup when there are foreign, like Hebrew, characters in xml files + +2021.12.19.0 + - Made kodi 19 (Matrix) compatible. + +2021.11.03.0 +- Fix Speedtest crash. + +2020.12.19.1 +- The plugin was also installed under Video add-ons. Now it only is in Program add-ons where it belongs +- Clean removed some files created by Common plugin cache or StorageServer or script.common.plugin.cache at kodi startup. + This resulted in breaking cache functionality of kodi +- Upload kodi log file to pastebin didn't always work and the first bytes were binary characters +- Made all decode calls UTF-8 +- Improved ADVANCED SETTINGS(BUFFER SIZE) functionality + diff --git a/changelog.txt b/changelog.txt index f15f8bb..e9eab60 100644 --- a/changelog.txt +++ b/changelog.txt @@ -10,7 +10,19 @@ v2020.12.19.1 - Improved ADVANCED SETTINGS(BUFFER SIZE) functionality v2021.11.03.0 -- Fix for kodi 20. Speedtest crashed. +- Fix Speedtest crash. + +v2021.12.19.0 + - Made kodi 19 (Matrix) compatible. v2022.12.28.0 - Fix backup. Crashed when foreign like Hebrew characters are used in xml files + +2023.01.01.0 + - Fix a fix on 2022.12.28.0 + +2023.01.09.0 + - Added AutoClean Cache functionality every x days at a given hour. + - Backup always replaced the home folder reference in xml files with special://home + Not all addons can handle this replace so it is now possible via a setting to disable this. + - Backup Cancel didn't work. This is now fixed. diff --git a/default.py b/default.py index 7a4a22b..fc0a8a2 100644 --- a/default.py +++ b/default.py @@ -5,22 +5,19 @@ import requests from resources.lib.modules import control, tools from resources.lib.modules.backtothefuture import unicode, PY2 +from resources.lib.modules import maintenance if PY2: quote_plus = urllib.quote_plus + translatePath = xbmc.translatePath else: quote_plus = urllib.parse.quote_plus + translatePath = xbmcvfs.translatePath AddonID ='script.ezmaintenanceplus' USER_AGENT = 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-GB; rv:1.9.0.3) Gecko/2008092417 Firefox/3.0.3' selfAddon = xbmcaddon.Addon(id=AddonID) -# Code to map the old translatePath -try: - translatePath = xbmcvfs.translatePath -except AttributeError: - translatePath = xbmc.translatePath - # ADDON SETTINGS wizard1 = control.setting('enable_wiz1') wizard2 = control.setting('enable_wiz2') @@ -82,6 +79,10 @@ def CAT_TOOLS(): print ("NONE YET") def MAINTENANCE(): + nextAutoCleanup = maintenance.getNextMaintenance() + if nextAutoCleanup > 0: + nextAutoCleanup = time.strftime("%a, %d %b %Y %I:%M:%S %p %Z", time.localtime(nextAutoCleanup)) + CreateDir('Next Auto Cleanup: %s' % nextAutoCleanup,'xxx','xxx',None,ADDON_FANART,'',isFolder=False,iconImage='DefaultIconInfo.png') CreateDir('Clear Cache','url','clear_cache',ADDON_ICON,ADDON_FANART,'') CreateDir('Clear Packages','url','clear_packages',ADDON_ICON,ADDON_FANART,'') CreateDir('Clear Thumbnails','url','clear_thumbs',ADDON_ICON,ADDON_FANART,'') @@ -201,15 +202,15 @@ def killxbmc(): -def CreateDir(name, url, action, icon, fanart, description, isFolder=False): +def CreateDir(name, url, action, icon, fanart, description, isFolder=False, iconImage="DefaultFolder.png"): if icon == None or icon == '': icon = ADDON_ICON u=sys.argv[0]+"?url="+quote_plus(url)+"&action="+str(action)+"&name="+quote_plus(name)+"&icon="+quote_plus(icon)+"&fanart="+quote_plus(fanart)+"&description="+quote_plus(description) ok=True if PY2: - liz=xbmcgui.ListItem(name, iconImage="DefaultFolder.png", thumbnailImage=icon) + liz=xbmcgui.ListItem(name, iconImage=iconImage, thumbnailImage=icon) else: liz=xbmcgui.ListItem(name) - liz.setArt({'icon':"DefaultFolder.png"}) + liz.setArt({'icon': iconImage}) liz.setArt({'thumbnailImage': icon}) liz.setInfo(type="Video", infoLabels={ "Title": name, "Plot": description } ) liz.setProperty( "Fanart_Image", fanart) @@ -261,7 +262,7 @@ def CreateDir(name, url, action, icon, fanart, description, isFolder=False): content = params.get('content') - +#xbmc.log("ezmaintenanceplus: action: %s" % action, level=xbmc.LOGINFO) if action == None: CATEGORIES() elif action == 'settings': control.openSettings() @@ -318,7 +319,5 @@ def CreateDir(name, url, action, icon, fanart, description, isFolder=False): elif action == 'speedtest': xbmc.executebuiltin('Runscript("special://home/addons/script.ezmaintenanceplus/resources/lib/modules/speedtest.py")') - - xbmcplugin.endOfDirectory(int(sys.argv[1])) diff --git a/resources/lib/modules/control.py b/resources/lib/modules/control.py index b86b151..1685469 100644 --- a/resources/lib/modules/control.py +++ b/resources/lib/modules/control.py @@ -8,6 +8,7 @@ import os,sys import xbmc,xbmcaddon,xbmcplugin,xbmcgui,xbmcvfs +from resources.lib.modules.backtothefuture import PY2 integer = 1000 @@ -78,11 +79,10 @@ listDir = xbmcvfs.listdir -# Code to map the old translatePath -try: - translatePath = xbmcvfs.translatePath -except AttributeError: +if PY2: translatePath = xbmc.translatePath +else: + translatePath = xbmcvfs.translatePath skinPath = translatePath('special://skin/') diff --git a/resources/lib/modules/logviewer.py b/resources/lib/modules/logviewer.py index 9edc675..627a30e 100644 --- a/resources/lib/modules/logviewer.py +++ b/resources/lib/modules/logviewer.py @@ -30,14 +30,6 @@ def open_Settings(): open_Settings = xbmcaddon.Addon(id=AddonID).openSettings() -def _get_keyboard( default="", heading="", hidden=False ): - """ shows a keyboard and returns a value """ - keyboard = xbmc.Keyboard( default, heading, hidden ) - keyboard.doModal() - if ( keyboard.isConfirmed() ): - return unicode( keyboard.getText()) - return default - def logView(): modes = ['View Log', 'Upload Log to Pastebin'] logPaths = [] diff --git a/resources/lib/modules/maintenance.py b/resources/lib/modules/maintenance.py index e5caa6f..baaa5d2 100644 --- a/resources/lib/modules/maintenance.py +++ b/resources/lib/modules/maintenance.py @@ -1,14 +1,17 @@ -import xbmc, xbmcaddon, xbmcgui, xbmcplugin, os, sys, xbmcvfs, glob +import xbmc, xbmcaddon, xbmcgui, xbmcplugin, os, sys, xbmcvfs, glob, math, time import shutil import urllib import re import os +from resources.lib.modules.backtothefuture import PY2 # Code to map the old translatePath -try: - translatePath = xbmcvfs.translatePath -except AttributeError: +if PY2: translatePath = xbmc.translatePath + loglevel = xbmc.LOGNOTICE +else: + translatePath = xbmcvfs.translatePath + loglevel = xbmc.LOGINFO thumbnailPath = translatePath('special://thumbnails'); cachePath = os.path.join(translatePath('special://home'), 'cache') @@ -169,3 +172,51 @@ def purgePackages(mode='verbose'): # dialog = xbmcgui.Dialog() # dialog.ok("Maintenance", "Deleting Packages all done") if mode == 'verbose': xbmc.executebuiltin('Notification(%s, %s, %s, %s)' % ('Maintenance' , 'Clean Packages Completed' , '3000', iconpath)) + +def determineNextMaintenance(): + getSetting = xbmcaddon.Addon().getSetting + + autoCleanDays = getSetting('autoCleanDays') + if autoCleanDays is None: + days = 0 + else: + days = int(autoCleanDays) + + t1 = 0 + + if days > 0: + autoCleanHour = getSetting('autoCleanHour') + if autoCleanHour is None: + hour = 0 + else: + hour = int(autoCleanHour) + + t0 = int(math.floor(time.time())) + + t1 = t0 + (days * 24 * 60 * 60) # days * 24h * 60m * 60s + + x = time.localtime(t1) + + t1 += (hour - x.tm_hour) * 60 * 60 - x.tm_min * 60 - x.tm_sec + while (t1 <= t0): + t1 += 24 * 60 * 60 # add days until we are in the future + + #t1 = t0 + 1 * 60 # for testing - every minute + + win = xbmcgui.Window(10000) + win.setProperty("ezmaintenance.nextMaintenanceTime", str(t1)) + + logMaintenance("setNextMaintenance: %s" % str(t1)) + + +def getNextMaintenance(): + win = xbmcgui.Window(10000) + t1 = int(win.getProperty("ezmaintenance.nextMaintenanceTime")) + + logMaintenance("getNextMaintenance: %s" % str(t1)) + + return t1 + +def logMaintenance(message): + xbmc.log("ezmaintenanceplus: %s" % message, level=loglevel) + diff --git a/resources/lib/modules/tools.py b/resources/lib/modules/tools.py index 96a17dd..e925f94 100644 --- a/resources/lib/modules/tools.py +++ b/resources/lib/modules/tools.py @@ -24,8 +24,10 @@ if PY2: FancyURLopener = urllib.FancyURLopener + translatePath = xbmc.translatePath else: FancyURLopener = urllib.request.FancyURLopener + translatePath = xbmcvfs.translatePath dp = xbmcgui.DialogProgress() dialog = xbmcgui.Dialog() @@ -34,11 +36,6 @@ AddonTitle="EZ Maintenance+" AddonID ='script.ezmaintenanceplus' -# Code to map the old translatePath -try: - translatePath = xbmcvfs.translatePath -except AttributeError: - translatePath = xbmc.translatePath def xml_data_advSettings_old(size): xml_data=""" @@ -68,18 +65,6 @@ def xml_data_advSettings_New(size): """ % size return xml_data - - - - - - -def write_ADV_SETTINGS_XML(file): - if not os.path.exists(xml_file): - with open(xml_file, "w") as f: - f.write(xml_data) - - def advancedSettings(): XML_FILE = translatePath(os.path.join('special://home/userdata' , 'advancedsettings.xml')) MEM = xbmc.getInfoLabel("System.Memory(total)") @@ -124,239 +109,5 @@ def _get_keyboard( default="", heading="", hidden=False, cancel="" ): return unicode( keyboard.getText()) return cancel -def ENABLE_ADDONS(): - for root, dirs, files in os.walk(HOME_ADDONS,topdown=True): - dirs[:] = [d for d in dirs] - for addon_name in dirs: - if not any(value in addon_name for value in EXCLUDES_ADDONS): - # addLink(addon_name,'url',100,ART+'tool.png',FANART,'') - try: - query = '{"jsonrpc":"2.0", "method":"Addons.SetAddonEnabled","params":{"addonid":"%s","enabled":true}, "id":1}' % (addon_name) - xbmc.executeJSONRPC(query) - - except: - pass - - -def FIX_SPECIAL(): - - HOME = translatePath('special://home') - dp.create(AddonTitle,"Renaming paths...") - url = translatePath('special://userdata') - for root, dirs, files in os.walk(url): - for file in files: - if file.endswith(".xml"): - if PY2: - dp.update(0,"Fixing", "[COLOR dodgerblue]" + file + "[/COLOR]") - else: - dp.update(0,"Fixing" + '\n' + "[COLOR dodgerblue]" + file + "[/COLOR]") - - try: - a = open((os.path.join(root, file)), 'r', encoding='utf-8').read() - b = a.replace(HOME, 'special://home/') - f = open((os.path.join(root, file)), mode='w', encoding='utf-8') - f.write(unicode(b)) - f.close() - except: - try: - a = open((os.path.join(root, file)), 'r').read() - b = a.replace(HOME, 'special://home/') - f = open((os.path.join(root, file)), mode='w') - f.write(unicode(b)) - f.close() - except: - pass - -def skinswap(): - - skin = xbmc.getSkinDir() - KODIV = float(xbmc.getInfoLabel("System.BuildVersion")[:4]) - skinswapped = 0 - - #SWITCH THE SKIN IF THE CURRENT SKIN IS NOT CONFLUENCE - if skin not in ['skin.confluence','skin.estuary']: - choice = xbmcgui.Dialog().yesno(AddonTitle, 'Please Wait while we try to reset to the default Kodi Skin...', yeslabel='Yes',nolabel='No') - if choice == 0: - sys.exit(1) - skin = 'skin.estuary' if KODIV >= 17 else 'skin.confluence' - skinSwitch.swapSkins(skin) - skinswapped = 1 - time.sleep(1) - - #IF A SKIN SWAP HAS HAPPENED CHECK IF AN OK DIALOG (CONFLUENCE INFO SCREEN) IS PRESENT, PRESS OK IF IT IS PRESENT - if skinswapped == 1: - if not xbmc.getCondVisibility("Window.isVisible(yesnodialog)"): - xbmc.executebuiltin( "Action(Select)" ) - - #IF THERE IS NOT A YES NO DIALOG (THE SCREEN ASKING YOU TO SWITCH TO CONFLUENCE) THEN SLEEP UNTIL IT APPEARS - if skinswapped == 1: - while not xbmc.getCondVisibility("Window.isVisible(yesnodialog)"): - time.sleep(1) - - #WHILE THE YES NO DIALOG IS PRESENT PRESS LEFT AND THEN SELECT TO CONFIRM THE SWITCH TO CONFLUENCE. - if skinswapped == 1: - while xbmc.getCondVisibility("Window.isVisible(yesnodialog)"): - xbmc.executebuiltin( "Action(Left)" ) - xbmc.executebuiltin( "Action(Select)" ) - time.sleep(1) - - skin = xbmc.getSkinDir() - - #CHECK IF THE SKIN IS NOT CONFLUENCE - if skin not in ['skin.confluence','skin.estuary']: - choice = xbmcgui.Dialog().yesno(AddonTitle, '[COLOR lightskyblue][B]ERROR: AUTOSWITCH WAS NOT SUCCESFULL[/B][/COLOR]' + '\n' + '[COLOR lightskyblue][B]CLICK YES TO MANUALLY SWITCH TO CONFLUENCE NOW[/B][/COLOR]' + '\n' + '[COLOR lightskyblue][B]YOU CAN PRESS NO AND ATTEMPT THE AUTO SWITCH AGAIN IF YOU WISH[/B][/COLOR]', yeslabel='[B][COLOR green]YES[/COLOR][/B]',nolabel='[B][COLOR lightskyblue]NO[/COLOR][/B]') - if choice == 1: - xbmc.executebuiltin("ActivateWindow(appearancesettings)") - return - else: - sys.exit(1) - - -# BACKUP ZIP -def backup(mode='full'): - backupdir = dialog.browse(type=0, heading='Select Backup Directory', shares='files',useThumbs=True, treatAsFolder=True, enableMultiple=False) - if mode == 'full': - BACKUPDATA = control.HOME - FIX_SPECIAL() - elif mode == 'userdata': BACKUPDATA = control.USERDATA - else: return - if os.path.exists(BACKUPDATA): - if not backupdir == '': - name = _get_keyboard(default='kodi_backup', heading='Name your Backup') - today = datetime.now().strftime('%Y%m%d%H%M') - today = re.sub('[^0-9]', '', str(today)) - zipDATE = "_%s.zip" % today - name = re.sub(' ','_', name) + zipDATE - backup_zip = translatePath(os.path.join(backupdir, name)) - exclude_database = ['.pyo','.log'] - exclude_dirs = ['cache','packages','Thumbnails'] - CreateZip(BACKUPDATA, backup_zip, 'Creating Backup', 'Backing up files', exclude_dirs, exclude_database) - dialog.ok(AddonTitle,'Backup complete') - else: - dialog.ok(AddonTitle,'No backup location found: Please setup your Backup location') - -def restore(): - yesDialog = dialog.yesno(AddonTitle, 'This will overwrite all your current settings ... Are you sure?', yeslabel='Yes', nolabel='No') - if yesDialog: - try: - zipFile = dialog.browse(type=1, heading='Select Backup File', shares='files',useThumbs=True, treatAsFolder=False, enableMultiple=False) - dp = xbmcgui.DialogProgress() - dp.create("Restoring File","In Progress..." + '\n' + "Please Wait") - dp.update(0, "" + '\n' + "Extracting Zip Please Wait") - ExtractZip(zipdir, control.HOME, dp) - dialog.ok(AddonTitle,'Restore Complete') - except:pass - -def CreateZip(folder, zip_filename, message_header, message1, exclude_dirs, exclude_files): - abs_src = os.path.abspath(folder) - for_progress = [] - ITEM =[] - dp = xbmcgui.DialogProgress() - dp.create(message_header, message1) - try: os.remove(zip_filename) - except: pass - for base, dirs, files in os.walk(folder): - for file in files: - ITEM.append(file) - N_ITEM =len(ITEM) - count = 0 - - zip_file = zipfile.ZipFile(zip_filename, 'w', zipfile.ZIP_DEFLATED, allowZip64 = True) - for dirpath, dirnames, filenames in os.walk(folder): - try: - dirnames[:] = [d for d in dirnames if d not in exclude_dirs] - filenames[:] = [f for f in filenames if f not in exclude_files] - - for file in filenames: - count += 1 - for_progress.append(file) - progress = len(for_progress) / float(N_ITEM) * 100 - if PY2: - dp.update(int(progress),"Backing Up", 'FILES: ' + str(count) + '/' + str(N_ITEM) + ' [COLOR lime]' + str(file) + '[/COLOR]', 'Please Wait') - else: - dp.update(int(progress),"Backing Up" + '\n' + 'FILES: ' + str(count) + '/' + str(N_ITEM) + ' [COLOR lime]' + str(file) + '[/COLOR]' + '\n' + 'Please Wait') - file = os.path.join(dirpath, file) - file = os.path.normpath(file) - arcname = file[len(abs_src) + 1:] - zip_file.write(file, arcname) - except:pass - zip_file.close() - - - -# EXTRACT ZIP -def ExtractZip(_in, _out, dp=None): - if dp: return ExtractWithProgress(_in, _out, dp) - return ExtractNOProgress(_in, _out) - -def ExtractNOProgress(_in, _out): - try: - zin = zipfile.ZipFile(_in, 'r') - zin.extractall(_out) - except Exception as e: - print(str(e)) - return True - -def ExtractWithProgress(_in, _out, dp): - zin = zipfile.ZipFile(_in, 'r') - nFiles = float(len(zin.infolist())) - count = 0 - errors = 0 - try: - for item in zin.infolist(): - count += 1 - update = count / nFiles * 100 - filenamefull = item.filename - if PY2: - dp.update(int(update),'Extracting... Errors: ' + str(errors) , label, '') - else: - dp.update(int(update),'Extracting... Errors: ' + str(errors) + '\n' + label) - try: zin.extract(item, _out) - except Exception as e: - print ("EXTRACTING ERRORS", e) - pass - - except Exception as e: - print(str(e)) - - - return True - - - -# DOWNLOADER -class customdownload(FancyURLopener): - version = 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11' - -def downloader(url, dest, dp = None): - if not dp: - dp = xbmcgui.DialogProgress() - dp.create(AddonTitle) - dp.update(0) - start_time=time.time() - customdownload().retrieve(url, dest, lambda nb, bs, fs, url=url: _pbhook(nb, bs, fs, dp, start_time)) - -def _pbhook(numblocks, blocksize, filesize, dp, start_time): - try: - percent = min(numblocks * blocksize * 100 / filesize, 100) - currently_downloaded = float(numblocks) * blocksize / (1024 * 1024) - kbps_speed = numblocks * blocksize / (time.time() - start_time) - if kbps_speed > 0: - eta = (filesize - numblocks * blocksize) / kbps_speed - else: - eta = 0 - kbps_speed = kbps_speed / 1024 - total = float(filesize) / (1024 * 1024) - mbs = '%.02f MB of %.02f MB' % (currently_downloaded, total) - e = 'Speed: %.02f Kb/s ' % kbps_speed - e += 'ETA: %02d:%02d' % divmod(eta, 60) - string = 'Downloading... Please Wait...' - dp.update(percent, mbs + '\n' + e + '\n' + string) - except: - percent = 100 - dp.update(percent) - if dp.iscanceled(): - raise Exception("Canceled") - dp.close() ############################## END ######################################### \ No newline at end of file diff --git a/resources/lib/modules/wiz.py b/resources/lib/modules/wiz.py index 5f86b73..0c451db 100644 --- a/resources/lib/modules/wiz.py +++ b/resources/lib/modules/wiz.py @@ -17,15 +17,17 @@ import re import time import zipfile -from resources.lib.modules import control, maintenance +from resources.lib.modules import control, maintenance, tools from datetime import datetime from resources.lib.modules.backtothefuture import unicode, PY2 if PY2: FancyURLopener = urllib.FancyURLopener from io import open as open + translatePath = xbmc.translatePath else: FancyURLopener = urllib.request.FancyURLopener + translatePath = xbmcvfs.translatePath unicode = str dp = xbmcgui.DialogProgress() @@ -35,11 +37,6 @@ AddonTitle="EZ Maintenance+" AddonID ='script.ezmaintenanceplus' -# Code to map the old translatePath -try: - translatePath = xbmcvfs.translatePath -except AttributeError: - translatePath = xbmc.translatePath def get_Kodi_Version(): try: KODIV = float(xbmc.getInfoLabel("System.BuildVersion")[:4]) @@ -49,14 +46,6 @@ def get_Kodi_Version(): def open_Settings(): open_Settings = xbmcaddon.Addon(id=AddonID).openSettings() -def _get_keyboard( default="", heading="", hidden=False ): - """ shows a keyboard and returns a value """ - keyboard = xbmc.Keyboard( default, heading, hidden ) - keyboard.doModal() - if ( keyboard.isConfirmed() ): - return unicode( keyboard.getText()) - return default - def ENABLE_ADDONS(): for root, dirs, files in os.walk(HOME_ADDONS,topdown=True): dirs[:] = [d for d in dirs] @@ -158,30 +147,37 @@ def backup(mode='full'): if mode == 'full': defaultName = "kodi_backup" BACKUPDATA = control.HOME - FIX_SPECIAL() + getSetting = xbmcaddon.Addon().getSetting + if getSetting('BackupFixSpecialHome') == 'true': + FIX_SPECIAL() elif mode == 'userdata': defaultName = "kodi_settings" BACKUPDATA = control.USERDATA else: return if os.path.exists(BACKUPDATA): if not backupdir == '': - name = _get_keyboard(default=defaultName, heading='Name your Backup') - today = datetime.now().strftime('%Y%m%d%H%M') - today = re.sub('[^0-9]', '', str(today)) - zipDATE = "_%s.zip" % today - name = re.sub(' ','_', name) + zipDATE - backup_zip = translatePath(os.path.join(backupdir, name)) - exclude_database = ['.pyo','.log'] - - try: - maintenance.clearCache(mode='silent') - maintenance.deleteThumbnails(mode='silent') - maintenance.purgePackages(mode='silent') - except:pass - - exclude_dirs = [''] - CreateZip(BACKUPDATA, backup_zip, 'Creating Backup', 'Backing up files', exclude_dirs, exclude_database) - dialog.ok(AddonTitle,'Backup complete') + name = tools._get_keyboard(default=defaultName, heading='Name your Backup', cancel="-") + if name != "-": + today = datetime.now().strftime('%Y%m%d%H%M') + today = re.sub('[^0-9]', '', str(today)) + zipDATE = "_%s.zip" % today + name = re.sub(' ','_', name) + zipDATE + backup_zip = translatePath(os.path.join(backupdir, name)) + exclude_database = ['.pyo','.log'] + + try: + maintenance.clearCache(mode='silent') + maintenance.deleteThumbnails(mode='silent') + maintenance.purgePackages(mode='silent') + except:pass + + exclude_dirs = [''] + canceled = CreateZip(BACKUPDATA, backup_zip, 'Creating Backup', 'Backing up files', exclude_dirs, exclude_database) + if canceled: + os.unlink(backup_zip) + dialog.ok(AddonTitle,'Backup canceled') + else: + dialog.ok(AddonTitle,'Backup complete') else: dialog.ok(AddonTitle,'No backup location found: Please setup your Backup location') @@ -208,8 +204,11 @@ def restore(zipFile): dp = xbmcgui.DialogProgress() dp.create("Restoring File","In Progress..." + '\n' + "Please Wait") dp.update(0, "" + '\n' + "Extracting Zip Please Wait") - ExtractZip(zipFile, control.HOME, dp) - dialog.ok(AddonTitle,'Restore Complete') + canceled = ExtractZip(zipFile, control.HOME, dp) + if canceled: + dialog.ok(AddonTitle,'Restore Canceled') + else: + dialog.ok(AddonTitle,'Restore Complete') xbmc.executebuiltin('ShutDown') except:pass @@ -227,14 +226,19 @@ def CreateZip(folder, zip_filename, message_header, message1, exclude_dirs, excl for file in files: ITEM.append(file) N_ITEM =len(ITEM) count = 0 - + canceled = False zip_file = zipfile.ZipFile(zip_filename, 'w', zipfile.ZIP_DEFLATED, allowZip64 = True) for dirpath, dirnames, filenames in os.walk(folder): + if canceled: + break try: dirnames[:] = [d for d in dirnames if d not in exclude_dirs] filenames[:] = [f for f in filenames if f not in exclude_files] for file in filenames: + if dp.iscanceled(): + canceled = True + break count += 1 for_progress.append(file) progress = len(for_progress) / float(N_ITEM) * 100 @@ -249,7 +253,7 @@ def CreateZip(folder, zip_filename, message_header, message1, exclude_dirs, excl except:pass zip_file.close() - + return canceled # EXTRACT ZIP def ExtractZip(_in, _out, dp=None): @@ -257,20 +261,26 @@ def ExtractZip(_in, _out, dp=None): return ExtractNOProgress(_in, _out) def ExtractNOProgress(_in, _out): + canceled = False + try: zin = zipfile.ZipFile(_in, 'r') zin.extractall(_out) except Exception as e: print(str(e)) - return True + return canceled def ExtractWithProgress(_in, _out, dp): zin = zipfile.ZipFile(_in, 'r') nFiles = float(len(zin.infolist())) count = 0 errors = 0 + canceled = False try: for item in zin.infolist(): + canceled = dp.iscanceled() + if canceled: + break count += 1 update = count / nFiles * 100 try: name = os.path.basename(item.filename) @@ -287,7 +297,7 @@ def ExtractWithProgress(_in, _out, dp): except Exception as e: print(str(e)) - return True + return canceled # INSTALL BUILD def buildInstaller(url): diff --git a/resources/settings.xml b/resources/settings.xml index e993534..b1097de 100644 --- a/resources/settings.xml +++ b/resources/settings.xml @@ -2,8 +2,11 @@ - - + + + + + @@ -37,6 +40,7 @@ + diff --git a/service.py b/service.py index da2a165..74a1c89 100644 --- a/service.py +++ b/service.py @@ -3,13 +3,16 @@ import urllib import re import time +from resources.lib.modules.backtothefuture import PY2 from resources.lib.modules import maintenance # Code to map the old translatePath -try: - translatePath = xbmcvfs.translatePath -except AttributeError: +if PY2: translatePath = xbmc.translatePath + loglevel = xbmc.LOGNOTICE +else: + translatePath = xbmcvfs.translatePath + loglevel = xbmc.LOGINFO AddonID ='script.ezmaintenanceplus' packagesdir = translatePath(os.path.join('special://home/addons/packages','')) @@ -61,7 +64,38 @@ time.sleep(3) if auto_clean == 'true': maintenance.clearCache() +maintenance.logMaintenance("Service started") + +class Monitor(xbmc.Monitor): + + def __init__(self): + xbmc.Monitor.__init__(self) + maintenance.logMaintenance("Monitor init") + maintenance.determineNextMaintenance() + + def onSettingsChanged(self): + maintenance.logMaintenance("onSettingsChanged") + maintenance.determineNextMaintenance() + +if __name__ == '__main__': + monitor = Monitor() + while not monitor.abortRequested(): + # Sleep/wait for abort for 10 seconds + if monitor.waitForAbort(10): + # Abort was requested while waiting. We should exit + break + maintenance.logMaintenance("monitor loop") + if not xbmc.Player().isPlayingVideo(): + nextMaintenance = maintenance.getNextMaintenance() + maintenance.logMaintenance("time.time() = %s, nextMaintenance = %s" % (str(time.time()), str(nextMaintenance))) + if nextMaintenance > 0 and time.time() >= nextMaintenance: + xbmc.log("ezmaintenanceplus: AutoClean started", level=loglevel) + maintenance.clearCache() + xbmc.log("ezmaintenanceplus: AutoClean done", level=loglevel) + maintenance.determineNextMaintenance() + #xbmc.executebuiltin('Notification(%s, %s, %s, %s)' % ('Maintenance' , 'Clean Completed' , '3000', iconpath)) + del monitor