def clear_thumbs(type=None): from resources.libs import db dialog = xbmcgui.Dialog() thumb_locations = {CONFIG.THUMBNAILS, os.path.join(CONFIG.ADDON_DATA, 'script.module.metadatautils', 'animatedgifs'), os.path.join(CONFIG.ADDON_DATA, 'script.extendedinfo', 'images')} latest = db.latest_db('Textures') if type is not None: choice = 1 else: choice = dialog.yesno(CONFIG.ADDONTITLE, '[COLOR {0}]Le gustaria eliminar {1} y las carpetas de miniaturas relacionadas?'.format(CONFIG.COLOR2, latest) + '\n' + "Ellas se repoblarán en la próxima puesta en marcha.[/COLOR]", nolabel='[B][COLOR red]No Eliminar[/COLOR][/B]', yeslabel='[B][COLOR dodgerblue]Eliminar Pulgares[/COLOR][/B]') if choice == 1: try: tools.remove_file(os.path.join(CONFIG.DATABASE, latest)) except: logging.log('Error al eliminar, Purgando DB.') db.purge_db_file(latest) for i in thumb_locations: tools.remove_folder(i) else: logging.log('Borrar nombres en miniatura cancelados') tools.redo_thumbs()
def clear_thumbs(type=None): from resources.libs import db dialog = xbmcgui.Dialog() thumb_locations = { CONFIG.THUMBNAILS, os.path.join(CONFIG.ADDON_DATA, 'script.module.metadatautils', 'animatedgifs'), os.path.join(CONFIG.ADDON_DATA, 'script.extendedinfo', 'images') } latest = db.latest_db('Textures') if type is not None: choice = 1 else: choice = dialog.yesno( CONFIG.ADDONTITLE, '[COLOR {0}]Would you like to delete the {1} and related thumbnail folders?' .format(CONFIG.COLOR2, latest) + '\n' + "They will repopulate on the next startup[/COLOR]", nolabel='[B][COLOR red]Don\'t Delete[/COLOR][/B]', yeslabel='[B][COLOR springgreen]Delete Thumbs[/COLOR][/B]') if choice == 1: try: tools.remove_file(os.path.join(CONFIG.DATABASE, latest)) except: logging.log('Failed to delete, Purging DB.') db.purge_db_file(latest) for i in thumb_locations: tools.remove_folder(i) else: logging.log('Clear thumbnames cancelled') tools.redo_thumbs()
def old_thumbs(): from resources.libs import db from resources.libs.common import tools dbfile = os.path.join(CONFIG.DATABASE, db.latest_db('Textures')) use = 30 week = tools.get_date(days=-7) ids = [] images = [] size = 0 if os.path.exists(dbfile): try: textdb = database.connect(dbfile, isolation_level=None) textexe = textdb.cursor() except Exception as e: logging.log("DB Connection Error: {0}".format(str(e)), level=xbmc.LOGERROR) return False else: logging.log('{0} not found.'.format(dbfile), level=xbmc.LOGERROR) return False textexe.execute( "SELECT idtexture FROM sizes WHERE usecount < ? AND lastusetime < ?", (use, str(week))) found = textexe.fetchall() for rows in found: idfound = rows[0] ids.append(idfound) textexe.execute("SELECT cachedurl FROM texture WHERE id = ?", (idfound, )) found2 = textexe.fetchall() for rows2 in found2: images.append(rows2[0]) logging.log("{0} total thumbs cleaned up.".format(str(len(images))), level=xbmc.LOGNOTICE) for id in ids: textexe.execute("DELETE FROM sizes WHERE idtexture = ?", (id, )) textexe.execute("DELETE FROM texture WHERE id = ?", (id, )) textexe.execute("VACUUM") textdb.commit() textexe.close() for image in images: path = os.path.join(CONFIG.THUMBNAILS, image) try: imagesize = os.path.getsize(path) os.remove(path) size += imagesize except: pass removed = tools.convert_size(size) if len(images) > 0: logging.log_notify( "[COLOR {0}]{1}[/COLOR]".format(CONFIG.COLOR1, CONFIG.ADDONTITLE), '[COLOR {0}]Clear Thumbs: {1} Files / {2} MB[/COLOR]!'.format( CONFIG.COLOR2, str(len(images)), removed)) else: logging.log_notify( "[COLOR {0}]{1}[/COLOR]".format(CONFIG.COLOR1, CONFIG.ADDONTITLE), '[COLOR {0}]Clear Thumbs: None Found![/COLOR]'.format( CONFIG.COLOR2))
def clear_thumbs(type=None): from resources.libs import db dialog = xbmcgui.Dialog() thumb_locations = {CONFIG.THUMBNAILS, os.path.join(CONFIG.ADDON_DATA, 'script.module.metadatautils', 'animatedgifs'), os.path.join(CONFIG.ADDON_DATA, 'script.extendedinfo', 'images')} latest = db.latest_db('Textures') if type is not None: choice = 1 else: choice = dialog.yesno(CONFIG.ADDONTITLE, '[COLOR {0}]Você gostaria de excluir o {1} e as pastas de miniaturas relacionadas?'.format(CONFIG.COLOR2, latest) + '\n' + "Eles irão repovoar na próxima inicialização[/COLOR]", nolabel='[B][COLOR red]Não apagar[/COLOR][/B]', yeslabel='[B][COLOR springgreen]Apagar Thumbs[/COLOR][/B]') if choice == 1: try: tools.remove_file(os.path.join(CONFIG.DATABASE, latest)) except: logging.log('Failed to delete, Purging DB.') db.purge_db_file(latest) for i in thumb_locations: tools.remove_folder(i) else: logging.log('Clear thumbnames cancelled') tools.redo_thumbs()
def old_thumbs(): from resources.libs import db from resources.libs.common import tools dbfile = os.path.join(CONFIG.DATABASE, db.latest_db('Textures')) use = 30 week = tools.get_date(days=-7) ids = [] images = [] size = 0 if os.path.exists(dbfile): try: textdb = database.connect(dbfile, isolation_level=None) textexe = textdb.cursor() except Exception as e: logging.log("DB Error de Conexion: {0}".format(str(e)), level=xbmc.LOGERROR) return False else: logging.log('{0} no encontrado.'.format(dbfile), level=xbmc.LOGERROR) return False textexe.execute("SELECCIONE id textura DESDE tamaños DONDE contar el usado < ? Y ultima hora de uso < ?", (use, str(week))) found = textexe.fetchall() for rows in found: idfound = rows[0] ids.append(idfound) textexe.execute("SELECCIONAR cache url DE textura DONDE id = ?", (idfound, )) found2 = textexe.fetchall() for rows2 in found2: images.append(rows2[0]) logging.log("{0} total de pulgares limpios.".format(str(len(images)))) for id in ids: textexe.execute("BORRAR DE tamaños DONDE id textura = ?", (id, )) textexe.execute("BORRAR DE textura DONDE id = ?", (id, )) textexe.execute("VACUUM") textdb.commit() textexe.close() for image in images: path = os.path.join(CONFIG.THUMBNAILS, image) try: imagesize = os.path.getsize(path) os.remove(path) size += imagesize except: pass removed = tools.convert_size(size) if len(images) > 0: logging.log_notify(CONFIG.ADDONTITLE, '[COLOR {0}]Pulgares Borrados: {1} Archivos / {2} MB[/COLOR]!'.format(CONFIG.COLOR2, str(len(images)), removed)) else: logging.log_notify(CONFIG.ADDONTITLE, '[COLOR {0}]Pulgares Borrados: Ninguno Encontrado![/COLOR]'.format(CONFIG.COLOR2))
def old_thumbs(): from resources.libs import db from resources.libs.common import tools dbfile = os.path.join(CONFIG.DATABASE, db.latest_db('Textures')) use = 30 week = tools.get_date(days=-7) ids = [] images = [] size = 0 if os.path.exists(dbfile): try: textdb = database.connect(dbfile, isolation_level=None) textexe = textdb.cursor() except Exception as e: logging.log("DB Connection Error: {0}".format(str(e)), level=xbmc.LOGERROR) return False else: logging.log('{0} not found.'.format(dbfile), level=xbmc.LOGERROR) return False textexe.execute("SELECIONE a textura de id de tamanhos ONDE nós contamos < ? AND lastusetime < ?", (use, str(week))) found = textexe.fetchall() for rows in found: idfound = rows[0] ids.append(idfound) textexe.execute("SELECIONE url em cache DA textura WHERE id = ?", (idfound, )) found2 = textexe.fetchall() for rows2 in found2: images.append(rows2[0]) logging.log("{0} total thumbs limpos.".format(str(len(images)))) for id in ids: textexe.execute("EXCLUIR DE tamanhos ONDE idtexture = ?", (id, )) textexe.execute("EXCLUIR DA textura ONDE id = ?", (id, )) textexe.execute("VACUUM") textdb.commit() textexe.close() for image in images: path = os.path.join(CONFIG.THUMBNAILS, image) try: imagesize = os.path.getsize(path) os.remove(path) size += imagesize except: pass removed = tools.convert_size(size) if len(images) > 0: logging.log_notify(CONFIG.ADDONTITLE, '[COLOR {0}]Limpar Thumbs: {1} Files / {2} MB[/COLOR]!'.format(CONFIG.COLOR2, str(len(images)), removed)) else: logging.log_notify(CONFIG.ADDONTITLE, '[COLOR {0}]Limpar Thumbs: Nenhum encontrado![/COLOR]'.format(CONFIG.COLOR2))
def remove_addon(addon, name, over=False, data=True): import sqlite3 from resources.libs import db if over: yes = 1 else: dialog = xbmcgui.Dialog() yes = dialog.yesno( CONFIG.ADDONTITLE, '[COLOR {0}]Are you sure you want to delete the add-on:'.format( CONFIG.COLOR2), 'Name: [COLOR {0}]{1}[/COLOR]'.format(CONFIG.COLOR1, name), 'ID: [COLOR {0}]{1}[/COLOR][/COLOR]'.format(CONFIG.COLOR1, addon), yeslabel='[B][COLOR springgreen]Remove Add-on[/COLOR][/B]', nolabel='[B][COLOR red]Don\'t Remove[/COLOR][/B]') if yes == 1: folder = os.path.join(CONFIG.ADDONS, addon) logging.log("Removing Add-on: {0}".format(addon)) from resources.libs.common import tools tools.clean_house(folder) xbmc.sleep(200) xbmc.executebuiltin('StopScript({0})'.format(addon)) sqldb = sqlite3.connect( os.path.join(CONFIG.DATABASE, db.latest_db('Addons'))) sqlexe = sqldb.cursor() query = "DELETE FROM {0} WHERE addonID = '{1}'" for table in ['addons', 'installed', 'package']: sqlexe.execute(query.format(table, addon)) try: shutil.rmtree(folder) except Exception as e: logging.log("Error removing {0}: {1}".format(addon, str(e)), level=xbmc.LOGNOTICE) if data: remove_addon_data(addon) return True if not over: logging.log_notify( "[COLOR {0}]{1}[/COLOR]".format(CONFIG.COLOR1, CONFIG.ADDONTITLE), "[COLOR {0}]{1} Removed[/COLOR]".format(CONFIG.COLOR2, name))
def remove_addon(addon, name, over=False, data=True): import sqlite3 from resources.libs import db if over: yes = 1 else: dialog = xbmcgui.Dialog() yes = dialog.yesno(CONFIG.ADDONTITLE, '[COLOR {0}]Estas seguro de que quieres eliminar el add-on:'.format(CONFIG.COLOR2) +'\n'+'Name: [COLOR {0}]{1}[/COLOR]'.format(CONFIG.COLOR1, name) +'\n'+'ID: [COLOR {0}]{1}[/COLOR][/COLOR]'.format(CONFIG.COLOR1, addon), yeslabel='[B][COLOR dodgerblue]Eliminar Add-on[/COLOR][/B]', nolabel='[B][COLOR red]No Eliminar[/COLOR][/B]') if yes == 1: folder = os.path.join(CONFIG.ADDONS, addon) logging.log("Eliminadno Add-on: {0}".format(addon)) from resources.libs.common import tools tools.clean_house(folder) xbmc.sleep(200) xbmc.executebuiltin('StopScript({0})'.format(addon)) sqldb = sqlite3.connect(os.path.join(CONFIG.DATABASE, db.latest_db('Addons'))) sqlexe = sqldb.cursor() query = "BORRAR DE {0} DONDE addonID = '{1}'" for table in ['addons', 'installed', 'package']: sqlexe.execute(query.format(table, addon)) try: shutil.rmtree(folder) except Exception as e: logging.log("Error al eliminar {0}: {1}".format(addon, str(e))) if data: remove_addon_data(addon) return True if not over: logging.log_notify(CONFIG.ADDONTITLE, "[COLOR {0}]{1} Eliminado[/COLOR]".format(CONFIG.COLOR2, name))
def wipe(): from resources.libs import db from resources.libs.common import logging from resources.libs import skin from resources.libs.common import tools from resources.libs import update if CONFIG.KEEPTRAKT == 'true': from resources.libs import traktit traktit.auto_update('all') CONFIG.set_setting('traktnextsave', str(tools.get_date(days=3, formatted=True))) if CONFIG.KEEPDEBRID == 'true': from resources.libs import debridit debridit.auto_update('all') CONFIG.set_setting('debridnextsave', str(tools.get_date(days=3, formatted=True))) if CONFIG.KEEPLOGIN == 'true': from resources.libs import loginit loginit.auto_update('all') CONFIG.set_setting('loginnextsave', str(tools.get_date(days=3, formatted=True))) exclude_dirs = CONFIG.EXCLUDES exclude_dirs.append('My_Builds') progress_dialog = xbmcgui.DialogProgress() skin.skin_to_default('Fresh Install') update.addon_updates('set') xbmcPath = os.path.abspath(CONFIG.HOME) progress_dialog.create(CONFIG.ADDONTITLE, "[COLOR {0}]Calculating files and folders".format(CONFIG.COLOR2) + '\n' + '\n' + 'Please Wait![/COLOR]') total_files = sum([len(files) for r, d, files in os.walk(xbmcPath)]) del_file = 0 progress_dialog.update(0, "[COLOR {0}]Gathering Excludes list.[/COLOR]".format(CONFIG.COLOR2)) if CONFIG.KEEPREPOS == 'true': repos = glob.glob(os.path.join(CONFIG.ADDONS, 'repo*/')) for item in repos: repofolder = os.path.split(item[:-1])[1] if not repofolder == exclude_dirs: exclude_dirs.append(repofolder) if CONFIG.KEEPSUPER == 'true': exclude_dirs.append('plugin.program.super.favourites') if CONFIG.KEEPWHITELIST == 'true': from resources.libs import whitelist whitelist = whitelist.whitelist('read') if len(whitelist) > 0: for item in whitelist: try: name, id, fold = item except: pass depends = db.depends_list(fold) for plug in depends: if plug not in exclude_dirs: exclude_dirs.append(plug) depends2 = db.depends_list(plug) for plug2 in depends2: if plug2 not in exclude_dirs: exclude_dirs.append(plug2) if fold not in exclude_dirs: exclude_dirs.append(fold) for item in CONFIG.DEPENDENCIES: exclude_dirs.append(item) progress_dialog.update(0, "[COLOR {0}]Clearing out files and folders:".format(CONFIG.COLOR2)) latestAddonDB = db.latest_db('Addons') for root, dirs, files in os.walk(xbmcPath, topdown=True): dirs[:] = [d for d in dirs if d not in exclude_dirs] for name in files: del_file += 1 fold = root.replace('/', '\\').split('\\') x = len(fold)-1 if name == 'sources.xml' and fold[-1] == 'userdata' and CONFIG.KEEPSOURCES == 'true': logging.log("Keep sources.xml: {0}".format(os.path.join(root, name))) elif name == 'favourites.xml' and fold[-1] == 'userdata' and CONFIG.KEEPFAVS == 'true': logging.log("Keep favourites.xml: {0}".format(os.path.join(root, name))) elif name == 'profiles.xml' and fold[-1] == 'userdata' and CONFIG.KEEPPROFILES == 'true': logging.log("Keep profiles.xml: {0}".format(os.path.join(root, name))) elif name == 'playercorefactory.xml' and fold[-1] == 'userdata' and CONFIG.KEEPPLAYERCORE == 'true': logging.log("Keep playercorefactory.xml: {0}".format(os.path.join(root, name))) elif name == 'guisettings.xml' and fold[-1] == 'userdata' and CONFIG.KEEPGUISETTINGS == 'true': logging.log("Keep guisettings.xml: {0}".format(os.path.join(root, name))) elif name == 'advancedsettings.xml' and fold[-1] == 'userdata' and CONFIG.KEEPADVANCED == 'true': logging.log("Keep advancedsettings.xml: {0}".format(os.path.join(root, name))) elif name in CONFIG.LOGFILES: logging.log("Keep Log File: {0}".format(name)) elif name.endswith('.db'): try: if name == latestAddonDB: logging.log("Ignoring {0} on Kodi {1}".format(name, tools.kodi_version())) else: os.remove(os.path.join(root, name)) except Exception as e: if not name.startswith('Textures13'): logging.log('Failed to delete, Purging DB') logging.log("-> {0}".format(str(e))) db.purge_db_file(os.path.join(root, name)) else: progress_dialog.update(int(tools.percentage(del_file, total_files)), '\n' + '[COLOR {0}]File: [/COLOR][COLOR {1}]{2}[/COLOR]'.format(CONFIG.COLOR2, CONFIG.COLOR1, name)) try: os.remove(os.path.join(root, name)) except Exception as e: logging.log("Error removing {0}".format(os.path.join(root, name))) logging.log("-> / {0}".format(str(e))) if progress_dialog.iscanceled(): progress_dialog.close() logging.log_notify(CONFIG.ADDONTITLE, "[COLOR {0}]Fresh Start Cancelled[/COLOR]".format(CONFIG.COLOR2)) return False for root, dirs, files in os.walk(xbmcPath, topdown=True): dirs[:] = [d for d in dirs if d not in exclude_dirs] for name in dirs: progress_dialog.update(100, '\n' + 'Cleaning Up Empty Folder: [COLOR {0}]{1}[/COLOR]'.format(CONFIG.COLOR1, name)) if name not in ["Database", "userdata", "temp", "addons", "addon_data"]: shutil.rmtree(os.path.join(root, name), ignore_errors=True, onerror=None) if progress_dialog.iscanceled(): progress_dialog.close() logging.log_notify(CONFIG.ADDONTITLE, "[COLOR {0}]Fresh Start Cancelled[/COLOR]".format(CONFIG.COLOR2)) return False progress_dialog.close() CONFIG.clear_setting('build')
def _backup_addon_data(name=""): dialog = xbmcgui.Dialog() progress_dialog = xbmcgui.DialogProgress() if dialog.yesno(CONFIG.ADDONTITLE, "[COLOR {0}]Are you sure you wish to backup the current addon_data?[/COLOR]".format(CONFIG.COLOR2), nolabel="[B][COLOR red]Cancel Backup[/COLOR][/B]", yeslabel="[B][COLOR springgreen]Backup Addon_Data[/COLOR][/B]"): if name == "": name = tools.get_keyboard("", "Please enter a name for the addon_data zip") if not name: return False name = quote_plus(name) name = '{0}_addondata.zip'.format(name) tempzipname = '' zipname = os.path.join(CONFIG.MYBUILDS, name) try: zipf = zipfile.ZipFile(xbmc.translatePath(zipname), mode='w') except: try: tempzipname = os.path.join(CONFIG.PACKAGES, '{0}.zip'.format(name)) zipf = zipfile.ZipFile(tempzipname, mode='w') except: logging.log("Unable to create {0}_addondata.zip".format(name), level=xbmc.LOGERROR) if dialog.yesno(CONFIG.ADDONTITLE, "[COLOR {0}]We are unable to write to the current backup directory, would you like to change the location?[/COLOR]".format(CONFIG.COLOR2), yeslabel="[B][COLOR springgreen]Change Directory[/COLOR][/B]", nolabel="[B][COLOR red]Cancel[/COLOR][/B]"): CONFIG.open_settings() return else: return for_progress = 0 ITEM = [] tools.convert_special(CONFIG.ADDON_DATA, True) tools.ascii_check(CONFIG.ADDON_DATA, True) progress_dialog.create("[COLOR {0}]{1}[/COLOR][COLOR {2}]: Creating Zip[/COLOR]".format(CONFIG.COLOR1, CONFIG.ADDONTITLE, CONFIG.COLOR2), "[COLOR {0}]Creating back up zip".format(CONFIG.COLOR2), "", "Please Wait...[/COLOR]") for base, dirs, files in os.walk(CONFIG.ADDON_DATA): dirs[:] = [d for d in dirs if d not in CONFIG.EXCLUDE_DIRS] files[:] = [f for f in files if f not in CONFIG.EXCLUDE_FILES] for file in files: ITEM.append(file) N_ITEM = len(ITEM) bad_files = [ (os.path.join(CONFIG.ADDON_DATA, 'plugin.video.exodusredux', 'cache.db')), (os.path.join(CONFIG.ADDON_DATA, 'plugin.video.exodusredux', 'cache.meta.5.db')), (os.path.join(CONFIG.ADDON_DATA, 'plugin.video.exodusredux', 'cache.providers.13.db')), (os.path.join(CONFIG.ADDON_DATA, 'plugin.video.thecrew', 'cache.db')), (os.path.join(CONFIG.ADDON_DATA, 'plugin.video.thecrew', 'cache.meta.5.db')), (os.path.join(CONFIG.ADDON_DATA, 'plugin.video.thecrew', 'cache.providers.13.db')), (os.path.join(CONFIG.ADDON_DATA, 'plugin.video.yoda', 'cache.db')), (os.path.join(CONFIG.ADDON_DATA, 'plugin.video.yoda', 'cache.meta.5.db')), (os.path.join(CONFIG.ADDON_DATA, 'plugin.video.yoda', 'cache.providers.13.db')), (os.path.join(CONFIG.ADDON_DATA, 'plugin.video.scrubsv2', 'cache.db')), (os.path.join(CONFIG.ADDON_DATA, 'plugin.video.scrubsv2', 'cache.meta.5.db')), (os.path.join(CONFIG.ADDON_DATA, 'plugin.video.scrubsv2', 'cache.providers.13.db')), (os.path.join(CONFIG.ADDON_DATA, 'plugin.video.gaia', 'cache.db')), (os.path.join(CONFIG.ADDON_DATA, 'plugin.video.gaia', 'meta.db')), (os.path.join(CONFIG.ADDON_DATA, 'plugin.video.seren', 'cache.db')), (os.path.join(CONFIG.ADDON_DATA, 'plugin.video.seren', 'torrentScrape.db')), (os.path.join(CONFIG.ADDON_DATA, 'script.module.simplecache', 'simplecache.db'))] for base, dirs, files in os.walk(CONFIG.ADDON_DATA): dirs[:] = [d for d in dirs if d not in CONFIG.EXCLUDE_DIRS] files[:] = [f for f in files if f not in CONFIG.EXCLUDE_FILES] for file in files: try: for_progress += 1 progress = tools.percentage(for_progress, N_ITEM) progress_dialog.update(int(progress), '[COLOR {0}]Creating back up zip: [COLOR{1}]{2}[/COLOR] / [COLOR{3}]{4}[/COLOR]'.format( CONFIG.COLOR2, CONFIG.COLOR1, for_progress, CONFIG.COLOR1, N_ITEM), '[COLOR {0}]{1}[/COLOR]'.format(CONFIG.COLOR1, file), '') fn = os.path.join(base, file) if file in CONFIG.LOGFILES: logging.log("[Back Up] Type = addon_data: Ignore {0} - Log Files".format(file)) continue elif os.path.join(base, file) in bad_files: logging.log("[Back Up] Type = addon_data: Ignore {0} - Cache Files".format(file)) continue elif os.path.join('addons', 'packages') in fn: logging.log("[Back Up] Type = addon_data: Ignore {0} - Packages Folder".format(file)) continue elif file.endswith('.csv'): logging.log("[Back Up] Type = addon_data: Ignore {0} - CSV File".format(file)) continue elif file.endswith('.db') and 'Database' in base: temp = file.replace('.db', '') temp = ''.join([i for i in temp if not i.isdigit()]) if temp in CONFIG.DB_FILES: if not file == db.latest_db(temp): logging.log("[Back Up] Type = addon_data: Ignore {0} - Database Files".format(file)) continue try: zipf.write(fn, fn[len(CONFIG.ADDON_DATA):], zipfile.ZIP_DEFLATED) except Exception as e: logging.log("[Back Up] Type = addon_data: Unable to backup {0}".format(file)) logging.log("Backup Error: {0}".format(str(e))) except Exception as e: logging.log("[Back Up] Type = addon_data: Unable to backup {0}".format(file)) logging.log("Backup Error: {0}".format(str(e))) zipf.close() if not tempzipname == '': success = xbmcvfs.rename(tempzipname, zipname) if success == 0: xbmcvfs.copy(tempzipname, zipname) xbmcvfs.delete(tempzipname) progress_dialog.close() dialog.ok(CONFIG.ADDONTITLE, "[COLOR {0}]{1}[/COLOR] [COLOR {2}]backup successful:[/COLOR]".format(CONFIG.COLOR1, name, CONFIG.COLOR2), "[COLOR {0}]{1}[/COLOR]".format(CONFIG.COLOR1, zipname))
def _backup_theme(name=""): dialog = xbmcgui.Dialog() if not dialog.yesno('[COLOR {0}]{1}[/COLOR][COLOR {2}]: Theme Backup[/COLOR]'.format(CONFIG.COLOR1, CONFIG.ADDONTITLE, CONFIG.COLOR2), "[COLOR {0}]Would you like to create a theme backup?[/COLOR]".format(CONFIG.COLOR2), yeslabel="[B][COLOR springgreen]Continue[/COLOR][/B]", nolabel="[B][COLOR red]No Cancel[/COLOR][/B]"): logging.log_notify("Theme Backup", "Cancelled!") return False if name == "": themename = tools.get_keyboard("", "Please enter a name for the theme zip") if not themename: return False else: themename = name themename = quote_plus(themename) tempzipname = '' zipname = os.path.join(CONFIG.MYBUILDS, '{0}.zip'.format(themename)) try: zipf = zipfile.ZipFile(zipname, mode='w') except: try: tempzipname = os.path.join(CONFIG.PACKAGES, '{0}.zip'.format(themename)) zipf = zipfile.ZipFile(tempzipname, mode='w') except: logging.log("Unable to create {0}.zip".format(themename), level=xbmc.LOGERROR) if dialog.yesno(CONFIG.ADDONTITLE, "[COLOR {0}]We are unable to write to the current backup directory, would you like to change the location?[/COLOR]".format(CONFIG.COLOR2), yeslabel="[B][COLOR springgreen]Change Directory[/COLOR][/B]", nolabel="[B][COLOR red]Cancel[/COLOR][/B]"): CONFIG.open_settings() return else: return tools.convert_special(CONFIG.USERDATA, True) tools.ascii_check(CONFIG.USERDATA, True) try: if not CONFIG.SKIN not in ['skin.confluence', 'skin.estuary', 'skin.estouchy']: skinfold = os.path.join(CONFIG.SKIN, 'media') match2 = glob.glob(os.path.join(skinfold, '*.xbt')) if len(match2) > 1: if dialog.yesno('[COLOR {0}]{1}[/COLOR][COLOR {2}]: Theme Backup[/COLOR]'.format(CONFIG.COLOR1, CONFIG.ADDONTITLE, CONFIG.COLOR2), "[COLOR {0}]Would you like to go through the Texture Files for?[/COLOR]".format(CONFIG.COLOR2), "[COLOR {0}]{1}[/COLOR]".format(CONFIG.COLOR1, CONFIG.SKIN), yeslabel="[B][COLOR springgreen]Add Textures[/COLOR][/B]", nolabel="[B][COLOR red]Skip Textures[/COLOR][/B]"): for xbt in match2: if dialog.yesno( '[COLOR {0}]{1}[/COLOR][COLOR {2}]: Theme Backup[/COLOR]'.format(CONFIG.COLOR1, CONFIG.ADDONTITLE, CONFIG.COLOR2), "[COLOR {0}]Would you like to add the Texture File [COLOR {1}]{2}[/COLOR]?".format( CONFIG.COLOR1, CONFIG.COLOR2, xbt.replace(skinfold, "")[1:]), "from [COLOR {0}]{1}[/COLOR][/COLOR]".format(CONFIG.COLOR1, CONFIG.SKIN), yeslabel="[B][COLOR springgreen]Add Textures[/COLOR][/B]", nolabel="[B][COLOR red]Skip Textures[/COLOR][/B]"): fn = xbt fn2 = fn.replace(CONFIG.HOME, "") zipf.write(fn, fn2, zipfile.ZIP_DEFLATED) else: for xbt in match2: if dialog.yesno( '[COLOR {0}]{1}[/COLOR][COLOR {2}]: Theme Backup[/COLOR]'.format(CONFIG.COLOR1, CONFIG.ADDONTITLE, CONFIG.COLOR2), "[COLOR {0}]Would you like to add the Texture File [COLOR {1}]{2}[/COLOR]?".format( CONFIG.COLOR2, CONFIG.COLOR1, xbt.replace(skinfold, "")[1:]), "from [COLOR {0}]{1}[/COLOR][/COLOR]".format(CONFIG.COLOR1, CONFIG.SKIN), yeslabel="[B][COLOR springgreen]Add Textures[/COLOR][/B]", nolabel="[B][COLOR red]Skip Textures[/COLOR][/B]"): fn = xbt fn2 = fn.replace(CONFIG.HOME, "") zipf.write(fn, fn2, zipfile.ZIP_DEFLATED) ad_skin = os.path.join(CONFIG.ADDON_DATA, CONFIG.SKIN, 'settings.xml') if os.path.exists(ad_skin): if dialog.yesno('[COLOR {0}]{1}[/COLOR][COLOR {2}]: Theme Backup[/COLOR]'.format(CONFIG.COLOR1, CONFIG.ADDONTITLE, CONFIG.COLOR2), "[COLOR {0}]Would you like to go add the [COLOR {1}]settings.xml[/COLOR] in [COLOR {2}]/addon_data/[/COLOR] for?".format( CONFIG.COLOR2, CONFIG.COLOR1, CONFIG.COLOR1), "[COLOR {0}]{1}[/COLOR]".format(CONFIG.COLOR1, CONFIG.SKIN), yeslabel="[B][COLOR springgreen]Add Settings[/COLOR][/B]", nolabel="[B][COLOR red]Skip Settings[/COLOR][/B]"): ad_skin2 = ad_skin.replace(CONFIG.HOME, "") zipf.write(ad_skin, ad_skin2, zipfile.ZIP_DEFLATED) match = tools.parse_dom(tools.read_from_file(os.path.join(CONFIG.SKIN, 'addon.xml')), 'import', ret='addon') if 'script.skinshortcuts' in match: if dialog.yesno('[COLOR {0}]{1}[/COLOR][COLOR {2}]: Theme Backup[/COLOR]'.format(CONFIG.COLOR1, CONFIG.ADDONTITLE, CONFIG.COLOR2), "[COLOR {0}]Would you like to go add the [COLOR {1}]settings.xml[/COLOR] for [COLOR {2}]script.skinshortcuts[/COLOR]?".format( CONFIG.COLOR2, CONFIG.COLOR1, CONFIG.COLOR1), yeslabel="[B][COLOR springgreen]Add Settings[/COLOR][/B]", nolabel="[B][COLOR red]Skip Settings[/COLOR][/B]"): for base, dirs, files in os.walk(os.path.join(CONFIG.ADDON_DATA, 'script.skinshortcuts')): files[:] = [f for f in files if f not in CONFIG.EXCLUDE_FILES] for file in files: fn = os.path.join(base, file) zipf.write(fn, fn[len(CONFIG.HOME):], zipfile.ZIP_DEFLATED) if dialog.yesno('[COLOR {0}]{1}[/COLOR][COLOR {2}]: Theme Backup[/COLOR]'.format(CONFIG.COLOR1, CONFIG.ADDONTITLE, CONFIG.COLOR2), "[COLOR {0}]Would you like to include a [COLOR {1}]Backgrounds[/COLOR] folder?[/COLOR]".format( CONFIG.COLOR2, CONFIG.COLOR1), yeslabel="[B][COLOR springgreen]Yes Include[/COLOR][/B]", nolabel="[B][COLOR red]No Continue[/COLOR][/B]"): fn = dialog.browse(0, 'Select location of backgrounds', 'files', '', True, False, CONFIG.HOME, False) if not fn == CONFIG.HOME: for base, dirs, files in os.walk(fn): dirs[:] = [d for d in dirs if d not in CONFIG.EXCLUDE_DIRS] files[:] = [f for f in files if f not in CONFIG.EXCLUDE_FILES] for file in files: try: fn2 = os.path.join(base, file) zipf.write(fn2, fn2[len(CONFIG.HOME):], zipfile.ZIP_DEFLATED) except Exception as e: logging.log("[Back Up] Type = theme: Unable to backup {0}".format(file)) logging.log("Backup Error: {0}".format(str(e))) text = db.latest_db('Textures') if dialog.yesno('[COLOR {0}]{1}[/COLOR][COLOR {2}]: Theme Backup[/COLOR]'.format(CONFIG.COLOR1, CONFIG.ADDONTITLE, CONFIG.COLOR2), "[COLOR {0}]Would you like to include the [COLOR {1}]{2}[/COLOR]?[/COLOR]".format( CONFIG.COLOR2, CONFIG.COLOR1, text), yeslabel="[B][COLOR springgreen]Yes Include[/COLOR][/B]", nolabel="[B][COLOR red]No Continue[/COLOR][/B]"): zipf.write(os.path.join(CONFIG.DATABASE, text), '/userdata/Database/{0}'.format(text), zipfile.ZIP_DEFLATED) if dialog.yesno('[COLOR {0}]{1}[/COLOR][COLOR {2}]: Theme Backup[/COLOR]'.format(CONFIG.COLOR1, CONFIG.ADDONTITLE, CONFIG.COLOR2), "[COLOR {0}]Would you like to include any addons?[/COLOR]".format(CONFIG.COLOR2), yeslabel="[B][COLOR springgreen]Yes Include[/COLOR][/B]", nolabel="[B][COLOR red]No Continue[/COLOR][/B]"): fold = glob.glob(os.path.join(CONFIG.ADDONS, '*/')) addonnames = [] addonfolds = [] for folder in sorted(fold, key=lambda x: x): foldername = os.path.split(folder[:-1])[1] if foldername in CONFIG.EXCLUDES: continue elif foldername in CONFIG.DEFAULTPLUGINS: continue elif foldername == 'packages': continue xml = os.path.join(folder, 'addon.xml') if os.path.exists(xml): match = tools.parse_dom(tools.read_from_file(xml), 'addon', ret='name') if len(match) > 0: addonnames.append(match[0]) addonfolds.append(foldername) else: addonnames.append(foldername) addonfolds.append(foldername) selected = dialog.multiselect("{0}: Select the add-ons you wish to add to the zip.".format(CONFIG.ADDONTITLE), addonnames) if selected is None: selected = [] if len(selected) > 0: added = [] for item in selected: added.append(addonfolds[item]) for base, dirs, files in os.walk(os.path.join(CONFIG.ADDONS, addonfolds[item])): files[:] = [f for f in files if f not in CONFIG.EXCLUDE_FILES] for file in files: if file.endswith('.pyo'): continue fn = os.path.join(base, file) zipf.write(fn, fn[len(CONFIG.HOME):], zipfile.ZIP_DEFLATED) dep = os.path.join(CONFIG.ADDONS, addonfolds[item], 'addon.xml') if os.path.exists(dep): match = tools.parse_dom(tools.read_from_file(dep), 'import', ret='addon') for depends in match: if 'xbmc.python' in depends: continue if depends in added: continue for base, dirs, files in os.walk(os.path.join(CONFIG.ADDONS, depends)): files[:] = [f for f in files if f not in CONFIG.EXCLUDE_FILES] for file in files: if file.endswith('.pyo'): continue fn = os.path.join(base, file) zipf.write(fn, fn[len(CONFIG.HOME):], zipfile.ZIP_DEFLATED) added.append(depends) if dialog.yesno('[COLOR {0}]{1}[/COLOR][COLOR {2}]: Theme Backup[/COLOR]'.format(CONFIG.COLOR1, CONFIG.ADDONTITLE, CONFIG.COLOR2), "[COLOR {0}]Would you like to include the [COLOR {1}]guisettings.xml[/COLOR]?[/COLOR]".format( CONFIG.COLOR2, CONFIG.COLOR1), yeslabel="[B][COLOR springgreen]Yes Include[/COLOR][/B]", nolabel="[B][COLOR red]No Continue[/COLOR][/B]"): zipf.write(CONFIG.GUISETTINGS, '/userdata/guisettings.xml', zipfile.ZIP_DEFLATED) except Exception as e: zipf.close() logging.log("[Back Up] Type = theme: {0}".format(str(e))) dialog.ok(CONFIG.ADDONTITLE, "[COLOR {0}]{1}[/COLOR][COLOR {2}] theme zip failed:[/COLOR]".format(CONFIG.COLOR1, themename, CONFIG.COLOR2), "[COLOR {0}]{1}[/COLOR]".format(CONFIG.COLOR1, str(e))) if not tempzipname == '': try: os.remove(tempzipname) except Exception as e: logging.log(str(e)) else: try: os.remove(zipname) except Exception as e: logging.log(str(e)) return zipf.close() if not tempzipname == '': success = xbmcvfs.rename(tempzipname, zipname) if success == 0: xbmcvfs.copy(tempzipname, zipname) xbmcvfs.delete(tempzipname) dialog.ok(CONFIG.ADDONTITLE, "[COLOR {0}]{1}[/COLOR][COLOR {2}] theme zip successful:[/COLOR]".format(CONFIG.COLOR1, themename, CONFIG.COLOR2), "[COLOR {0}]{1}[/COLOR]".format(CONFIG.COLOR1, zipname))
def _backup_build(name=""): dialog = xbmcgui.Dialog() progress_dialog = xbmcgui.DialogProgress() if dialog.yesno(CONFIG.ADDONTITLE, "[COLOR {0}]Are you sure you wish to backup the current build?[/COLOR]".format(CONFIG.COLOR2), nolabel="[B][COLOR red]Cancel Backup[/COLOR][/B]", yeslabel="[B][COLOR springgreen]Backup Build[/COLOR][/B]"): if name == "": name = tools.get_keyboard("", "Please enter a name for the build zip") if not name: return False name = name.replace('\\', '').replace('/', '').replace(':', '').replace('*', '').replace('?', '').replace( '"', '').replace('<', '').replace('>', '').replace('|', '') name = quote_plus(name) tempzipname = '' zipname = os.path.join(CONFIG.MYBUILDS, '{0}.zip'.format(name)) for_progress = 0 ITEM = [] exclude_dirs = CONFIG.EXCLUDE_DIRS if not dialog.yesno(CONFIG.ADDONTITLE, "[COLOR {0}]Do you want to include your addon_data folder?".format(CONFIG.COLOR2), "This contains [COLOR {0}]ALL[/COLOR] add-on settings including passwords but may also contain important information such as skin shortcuts. We recommend [COLOR {0}]MANUALLY[/COLOR] removing the addon_data folders that aren\'t required.".format(CONFIG.COLOR1, CONFIG.COLOR1), "[COLOR {0}]{1}[/COLOR] addon_data is ignored[/COLOR]".format(CONFIG.COLOR1, CONFIG.ADDON_ID), yeslabel='[B][COLOR springgreen]Include data[/COLOR][/B]', nolabel='[B][COLOR red]Don\'t Include[/COLOR][/B]'): exclude_dirs.append('addon_data') tools.convert_special(CONFIG.HOME, True) # tools.ascii_check(CONFIG.HOME, True) extractsize = 0 try: zipf = zipfile.ZipFile(xbmc.translatePath(zipname), mode='w') except: try: tempzipname = os.path.join(CONFIG.PACKAGES, '{0}.zip'.format(name)) zipf = zipfile.ZipFile(tempzipname, mode='w') except: logging.log("Unable to create {0}.zip".format(name), level=xbmc.LOGERROR) if dialog.yesno(CONFIG.ADDONTITLE, "[COLOR {0}]We are unable to write to the current backup directory, would you like to change the location?[/COLOR]".format(CONFIG.COLOR2), yeslabel="[B][COLOR springgreen]Change Directory[/COLOR][/B]", nolabel="[B][COLOR red]Cancel[/COLOR][/B]"): CONFIG.open_settings() return else: return progress_dialog.create("[COLOR {0}]{1}[/COLOR][COLOR {2}]: Creating Zip[/COLOR]".format(CONFIG.COLOR1, CONFIG.ADDONTITLE, CONFIG.COLOR2), "[COLOR {0}]Creating backup zip".format(CONFIG.COLOR2), "", "Please Wait...[/COLOR]") for base, dirs, files in os.walk(CONFIG.HOME): dirs[:] = [d for d in dirs if d not in exclude_dirs] files[:] = [f for f in files if f not in CONFIG.EXCLUDE_FILES] for file in files: ITEM.append(file) N_ITEM = len(ITEM) picture = [] music = [] video = [] programs = [] repos = [] scripts = [] skins = [] fold = glob.glob(os.path.join(CONFIG.ADDONS, '*/')) idlist = [] binaries = [] binidlist = [] for folder in sorted(fold, key=lambda x: x): foldername = os.path.split(folder[:-1])[1] if foldername == 'packages': continue binaryid, binaryname = db.find_binary_addons(addon=foldername) if binaryid: binaries.append(binaryname) binidlist.append(binaryid) xml = os.path.join(folder, 'addon.xml') if os.path.exists(xml): a = tools.read_from_file(xml) prov = re.compile("<provides>(.+?)</provides>").findall(a) match = tools.parse_dom(prov, 'addon', ret='id') addid = foldername if len(match) == 0 else match[0] if addid in idlist: continue idlist.append(addid) try: add = xbmcaddon.Addon(id=addid) aname = add.getAddonInfo('name') aname = aname.replace('[', '<').replace(']', '>') aname = str(re.sub('<[^<]+?>', '', aname)).lstrip() except: aname = foldername if len(prov) == 0: if foldername.startswith('skin'): skins.append(aname) elif foldername.startswith('repo'): repos.append(aname) else: scripts.append(aname) continue if not (prov[0]).find('executable') == -1: programs.append(aname) if not (prov[0]).find('video') == -1: video.append(aname) if not (prov[0]).find('audio') == -1: music.append(aname) if not (prov[0]).find('image') == -1: picture.append(aname) db.fix_metas() binarytxt = _backup_binaries(binidlist) for base, dirs, files in os.walk(CONFIG.HOME): dirs[:] = [d for d in dirs if d not in exclude_dirs] files[:] = [f for f in files if f not in CONFIG.EXCLUDE_FILES] for file in files: try: for_progress += 1 progress = tools.percentage(for_progress, N_ITEM) progress_dialog.update(int(progress), '[COLOR {0}]Creating backup zip: [COLOR {1}]{2}[/COLOR] / [COLOR {3}]{4}[/COLOR]'.format( CONFIG.COLOR2, CONFIG.COLOR1, for_progress, CONFIG.COLOR1, N_ITEM), '[COLOR {0}]{1}[/COLOR]'.format(CONFIG.COLOR1, file), '') fn = os.path.join(base, file) if file in CONFIG.LOGFILES: logging.log("[Back Up] Type = build: Ignore {0} - Log File".format(file)) continue elif os.path.join(base, file) in CONFIG.EXCLUDE_FILES: logging.log("[Back Up] Type = build: Ignore {0} - Excluded File".format(file)) continue elif os.path.join('addons', 'packages') in fn: logging.log("[Back Up] Type = build: Ignore {0} - Packages Folder".format(file)) continue elif file.endswith('.csv'): logging.log("[Back Up] Type = build: Ignore {0} - CSV File".format(file)) continue elif file.endswith('.pyo'): continue elif file.endswith('.db') and 'Database' in base: temp = file.replace('.db', '') temp = ''.join([i for i in temp if not i.isdigit()]) if temp in CONFIG.DB_FILES: if not file == db.latest_db(temp): logging.log("[Back Up] Type = build: Ignore {0} - DB File".format(file)) continue skipbinary = False if len(binidlist) > 0: for id in binidlist: id = os.path.join(CONFIG.ADDONS, id) if id in fn: skipbinary = True if skipbinary: logging.log("[Back Up] Type = build: Ignore {0} - Binary Add-on".format(file)) continue try: zipf.write(fn, fn[len(CONFIG.HOME):], zipfile.ZIP_DEFLATED) extractsize += os.path.getsize(fn) except Exception as e: logging.log("[Back Up] Type = build: Unable to backup {0}".format(file)) logging.log("{0} / {1}".format(Exception, e)) if progress_dialog.iscanceled(): progress_dialog.close() logging.log_notify("[COLOR {0}]{1}[/COLOR]".format(CONFIG.COLOR1, CONFIG.ADDONTITLE), "[COLOR {0}]Backup Cancelled[/COLOR]".format(CONFIG.COLOR2)) sys.exit() except Exception as e: logging.log("[Back Up] Type = build: Unable to backup {0}".format(file)) logging.log("Build Backup Error: {0}".format(str(e))) if 'addon_data' in exclude_dirs: match = glob.glob(os.path.join(CONFIG.ADDON_DATA, 'skin.*', '')) for fold in match: fd = os.path.split(fold[:-1])[1] if fd not in ['skin.confluence', 'skin.estuary', 'skin.estouchy']: for base, dirs, files in os.walk(os.path.join(CONFIG.ADDON_DATA, fold)): files[:] = [f for f in files if f not in CONFIG.EXCLUDE_FILES] for file in files: fn = os.path.join(base, file) zipf.write(fn, fn[len(CONFIG.HOME):], zipfile.ZIP_DEFLATED) extractsize += os.path.getsize(fn) xml = os.path.join(CONFIG.ADDONS, fd, 'addon.xml') if os.path.exists(xml): matchxml = tools.parse_dom(tools.read_from_file(xml), 'import', ret='addon') if 'script.skinshortcuts' in matchxml: for base, dirs, files in os.walk(os.path.join(CONFIG.ADDON_DATA, 'script.skinshortcuts')): files[:] = [f for f in files if f not in CONFIG.EXCLUDE_FILES] for file in files: fn = os.path.join(base, file) zipf.write(fn, fn[len(CONFIG.HOME):], zipfile.ZIP_DEFLATED) extractsize += os.path.getsize(fn) zipf.close() xbmc.sleep(500) progress_dialog.close() backup('guifix', name) if not tempzipname == '': success = xbmcvfs.rename(tempzipname, zipname) if success == 0: xbmcvfs.copy(tempzipname, zipname) xbmcvfs.delete(tempzipname) if binarytxt is not None: bintxtpath = os.path.join(CONFIG.USERDATA, binarytxt) xbmcvfs.delete(bintxtpath) _backup_info(name, extractsize, programs, video, music, picture, repos, scripts, binaries) if len(binaries) > 0: dialog.ok(CONFIG.ADDONTITLE, "[COLOR {0}]The following add-ons were excluded from the backup because they are platform specific:[/COLOR]".format(CONFIG.COLOR2), "[COLOR {0}]{1}[/COLOR]".format(CONFIG.COLOR1, ', '.join(binaries))) dialog.ok(CONFIG.ADDONTITLE, "[COLOR {0}]{1}[/COLOR] [COLOR {2}]Backup successful:[/COLOR]".format(CONFIG.COLOR1, name, CONFIG.COLOR2), "[COLOR {0}]{1}[/COLOR]".format(CONFIG.COLOR1, zipname))