def getsize(path, silent=False, vfs=True): """ Obtiene el tamaño de un archivo @param path: ruta del fichero @type path: str @rtype: str @return: tamaño del fichero """ path = encode(path) try: if xbmc_vfs and vfs: if not exists(path): return long(0) f = xbmcvfs.File(path) s = f.size() f.close() return s elif path.lower().startswith("smb://"): return long(samba.get_attributes(path).file_size) else: return os.path.getsize(path) except: logger.error("ERROR when getting the size: %s" % path) if not silent: logger.error(traceback.format_exc()) return long(0)
def isdir(path, silent=False, vfs=True): """ Comprueba si la ruta es un directorio @param path: ruta @type path: str @rtype: bool @return: Retorna True si la ruta existe y es un directorio """ path = encode(path) try: if xbmc_vfs and vfs: if not scrapertools.find_single_match(path, '(^\w+:\/\/)'): return os.path.isdir(path) if path.endswith('/') or path.endswith('\\'): path = path[:-1] dirs, files = xbmcvfs.listdir(dirname(path)) base_name = basename(path) for dir in dirs: if base_name == dir: return True return False elif path.lower().startswith("smb://"): return samba.isdir(path) else: return os.path.isdir(path) except: logger.error("ERROR when checking the directory: %s" % path) if not silent: logger.error(traceback.format_exc()) return False
def file_open(path, mode="r", silent=False, vfs=True): """ Abre un archivo @param path: ruta @type path: str @rtype: str @return: objeto file """ path = encode(path) try: if xbmc_vfs and vfs: if 'r' in mode and '+' in mode: mode = mode.replace('r', 'w').replace('+', '') logger.debug('Open MODE changed to: %s' % mode) if 'a' in mode: mode = mode.replace('a', 'w').replace('+', '') logger.debug('Open MODE changed to: %s' % mode) return xbmcvfs.File(path, mode) elif path.lower().startswith("smb://"): return samba.smb_open(path, mode) else: return open(path, mode) except: logger.error("ERROR when opening file: %s, %s" % (path, mode)) if not silent: logger.error(traceback.format_exc()) platformtools.dialog_notification("Error Opening", path) return False
def rmdir(path, silent=False, vfs=True): """ Elimina un directorio @param path: ruta a eliminar @type path: str @rtype: bool @return: devuelve False en caso de error """ path = encode(path) try: if xbmc_vfs and vfs: if not path.endswith('/') and not path.endswith('\\'): path = join(path, ' ').rstrip() return bool(xbmcvfs.rmdir(path)) elif path.lower().startswith("smb://"): samba.rmdir(path) else: os.rmdir(path) except: logger.error("ERROR deleting directory: %s" % path) if not silent: logger.error(traceback.format_exc()) platformtools.dialog_notification("ERROR deleting directory", path) return False else: return True
def write(path, data, mode="wb", silent=False, vfs=True): """ Guarda los datos en un archivo @param path: ruta del archivo a guardar @type path: str @param data: datos a guardar @type data: str @rtype: bool @return: devuelve True si se ha escrito correctamente o False si ha dado un error """ path = encode(path) try: if xbmc_vfs and vfs: f = xbmcvfs.File(path, mode) result = f.write(data) f.close() return bool(result) elif path.lower().startswith("smb://"): f = samba.smb_open(path, mode) else: f = open(path, mode) f.write(data) f.close() except: logger.error("ERROR al guardar el archivo: %s" % path) if not silent: logger.error(traceback.format_exc()) return False else: return True
def mkdir(path, silent=False, vfs=True): """ Crea un directorio @param path: ruta a crear @type path: str @rtype: bool @return: devuelve False en caso de error """ path = encode(path) try: if xbmc_vfs and vfs: if not path.endswith('/') and not path.endswith('\\'): path = join(path, ' ').rstrip() result = bool(xbmcvfs.mkdirs(path)) if not result: import time time.sleep(0.1) result = exists(path) return result elif path.lower().startswith("smb://"): samba.mkdir(path) else: os.mkdir(path) except: logger.error("ERROR when creating directory: %s" % path) if not silent: logger.error(traceback.format_exc()) platformtools.dialog_notification("ERROR when creating directory", path) return False else: return True
def removeTree(dir): if os.path.isdir(dir): try: shutil.rmtree(dir, ignore_errors=False, onerror=onerror) except Exception as e: logger.info('Cartella ' + dir + ' NON eliminata') logger.error(e)
def exists(path, silent=False, vfs=True): """ Comprueba si existe una carpeta o fichero @param path: ruta @type path: str @rtype: bool @return: Retorna True si la ruta existe, tanto si es una carpeta como un archivo """ path = encode(path) try: if xbmc_vfs and vfs: result = bool(xbmcvfs.exists(path)) if not result and not path.endswith('/') and not path.endswith( '\\'): result = bool(xbmcvfs.exists(join(path, ' ').rstrip())) return result elif path.lower().startswith("smb://"): return samba.exists(path) else: return os.path.exists(path) except: logger.error("ERROR when checking the path: %s" % path) if not silent: logger.error(traceback.format_exc()) return False
def _pbhook(numblocks, blocksize, filesize, url, dp): try: percent = min((numblocks*blocksize*80)/filesize, 80) dp.update(int(percent)) except Exception as e: logger.error(e) percent = 80 dp.update(percent)
def set_setting(name, value, channel="", server=""): """ Fija el valor de configuracion del parametro indicado. Establece 'value' como el valor del parametro 'name' en la configuracion global o en la configuracion propia del canal 'channel'. Devuelve el valor cambiado o None si la asignacion no se ha podido completar. Si se especifica el nombre del canal busca en la ruta \addon_data\plugin.video.alfa\settings_channels el archivo channel_data.json y establece el parametro 'name' al valor indicado por 'value'. Si el archivo channel_data.json no existe busca en la carpeta channels el archivo channel.json y crea un archivo channel_data.json antes de modificar el parametro 'name'. Si el parametro 'name' no existe lo añade, con su valor, al archivo correspondiente. Parametros: name -- nombre del parametro value -- valor del parametro channel [opcional] -- nombre del canal Retorna: 'value' en caso de que se haya podido fijar el valor y None en caso contrario """ if channel: from core import channeltools return channeltools.set_channel_setting(name, value, channel) elif server: from core import servertools return servertools.set_server_setting(name, value, server) else: try: if isinstance(value, bool): if value: value = "true" else: value = "false" elif isinstance(value, (int, long)): value = str(value) __settings__.setSetting(name, value) except Exception as ex: from dependencies import logger logger.error("Error al convertir '%s' no se guarda el valor \n%s" % (name, ex)) return None return value
def copy(path, dest, silent=False, vfs=True): """ Copia un archivo @param path: ruta del fichero a copiar @type path: str @param dest: ruta donde copiar @type dest: str @param silent: se muestra o no el cuadro de dialogo @type silent: bool @rtype: bool @return: devuelve False en caso de error """ try: if xbmc_vfs and vfs: path = encode(path) dest = encode(dest) if not silent: dialogo = platformtools.dialog_progress("Copiando archivo", "") return bool(xbmcvfs.copy(path, dest)) fo = file_open(path, "rb") fd = file_open(dest, "wb") if fo and fd: if not silent: dialogo = platformtools.dialog_progress("Copiando archivo", "") size = getsize(path) copiado = 0 while True: if not silent: dialogo.update(old_div(copiado * 100, size), basename(path)) buf = fo.read(1024 * 1024) if not buf: break if not silent and dialogo.iscanceled(): dialogo.close() return False fd.write(buf) copiado += len(buf) if not silent: dialogo.close() except: logger.error("ERROR when copying the file: %s" % path) if not silent: logger.error(traceback.format_exc()) return False else: return True
def file_stat(path, silent=False, vfs=True): """ Stat de un archivo @param path: ruta @type path: str @rtype: str @return: objeto file """ path = encode(path) try: if xbmc_vfs and vfs: if not exists(path): return False return xbmcvfs.Stat(path) raise except: logger.error("File_Stat not supported: %s" % path) if not silent: logger.error(traceback.format_exc()) return False
def rmdirtree(path, silent=False, vfs=True): """ Elimina un directorio y su contenido @param path: ruta a eliminar @type path: str @rtype: bool @return: devuelve False en caso de error """ path = encode(path) try: if xbmc_vfs and vfs: if not exists(path): return True if not path.endswith('/') and not path.endswith('\\'): path = join(path, ' ').rstrip() for raiz, subcarpetas, ficheros in walk(path, topdown=False): for f in ficheros: xbmcvfs.delete(join(raiz, f)) for s in subcarpetas: xbmcvfs.rmdir(join(raiz, s)) xbmcvfs.rmdir(path) elif path.lower().startswith("smb://"): for raiz, subcarpetas, ficheros in samba.walk(path, topdown=False): for f in ficheros: samba.remove(join(decode(raiz), decode(f))) for s in subcarpetas: samba.rmdir(join(decode(raiz), decode(s))) samba.rmdir(path) else: import shutil shutil.rmtree(path, ignore_errors=True) except: logger.error("ERROR deleting directory: %s" % path) if not silent: logger.error(traceback.format_exc()) platformtools.dialog_notification("ERROR deleting directory", path) return False else: return not exists(path)
def listdir(path, silent=False, vfs=True): """ Lista un directorio @param path: Directorio a listar, debe ser un str "UTF-8" @type path: str @rtype: str @return: contenido de un directorio """ path = encode(path) try: if xbmc_vfs and vfs: dirs, files = xbmcvfs.listdir(path) return dirs + files elif path.lower().startswith("smb://"): return decode(samba.listdir(path)) else: return decode(os.listdir(path)) except: logger.error("ERROR when reading the directory: %s" % path) if not silent: logger.error(traceback.format_exc()) return False
def remove(path, silent=False, vfs=True): """ Elimina un archivo @param path: ruta del fichero a eliminar @type path: str @rtype: bool @return: devuelve False en caso de error """ path = encode(path) try: if xbmc_vfs and vfs: return bool(xbmcvfs.delete(path)) elif path.lower().startswith("smb://"): samba.remove(path) else: os.remove(path) except: logger.error("ERROR deleting file: %s" % path) if not silent: logger.error(traceback.format_exc()) platformtools.dialog_notification("ERROR deleting file", path) return False else: return True
def move(path, dest, silent=False, strict=False, vfs=True): """ Mueve un archivo @param path: ruta del fichero a mover @type path: str @param dest: ruta donde mover @type dest: str @rtype: bool @return: devuelve False en caso de error """ try: if xbmc_vfs and vfs: if not exists(path): return False path = encode(path) dest = encode(dest) result = xbmcvfs.rename(path, dest) if not result and not strict: logger.error( "ERROR when MOVING the file: %s. Copying and deleting" % path) if not silent: dialogo = platformtools.dialog_progress("Copying file", "") result = xbmcvfs.copy(path, dest) if not result: return False xbmcvfs.delete(path) return bool(result) # samba/samba elif path.lower().startswith("smb://") and dest.lower().startswith( "smb://"): dest = encode(dest, True) path = encode(path, True) samba.rename(path, dest) # local/local elif not path.lower().startswith( "smb://") and not dest.lower().startswith("smb://"): dest = encode(dest) path = encode(path) os.rename(path, dest) # mixto En este caso se copia el archivo y luego se elimina el de origen else: if not silent: dialogo = platformtools.dialog_progress("Copiando archivo", "") return copy(path, dest) == True and remove(path) == True except: logger.error("ERROR when moving file: %s to %s" % (path, dest)) if not silent: logger.error(traceback.format_exc()) return False else: return True
def rename(path, new_name, silent=False, strict=False, vfs=True): """ Renombra un archivo o carpeta @param path: ruta del fichero o carpeta a renombrar @type path: str @param new_name: nuevo nombre @type new_name: str @rtype: bool @return: devuelve False en caso de error """ path = encode(path) try: if xbmc_vfs and vfs: path_end = path if path_end.endswith('/') or path_end.endswith('\\'): path_end = path_end[:-1] dest = encode(join(dirname(path_end), new_name)) result = xbmcvfs.rename(path, dest) if not result and not strict: logger.error("ERROR RENAME file: %s. Copying and deleting" % path) if not silent: dialogo = platformtools.dialog_progress("Copying file", "") result = xbmcvfs.copy(path, dest) if not result: return False xbmcvfs.delete(path) return bool(result) elif path.lower().startswith("smb://"): new_name = encode(new_name, True) samba.rename(path, join(dirname(path), new_name)) else: new_name = encode(new_name, False) os.rename(path, os.path.join(os.path.dirname(path), new_name)) except: logger.error("ERROR when renaming the file: %s" % path) if not silent: logger.error(traceback.format_exc()) platformtools.dialog_notification("Error renaming", path) return False else: return True
def read(path, linea_inicio=0, total_lineas=None, whence=0, silent=False, vfs=True): """ Lee el contenido de un archivo y devuelve los datos @param path: ruta del fichero @type path: str @param linea_inicio: primera linea a leer del fichero @type linea_inicio: int positivo @param total_lineas: numero maximo de lineas a leer. Si es None o superior al total de lineas se leera el fichero hasta el final. @type total_lineas: int positivo @rtype: str @return: datos que contiene el fichero """ path = encode(path) try: if not isinstance(linea_inicio, int): try: linea_inicio = int(linea_inicio) except: logger.error('Read: Start_line ERROR: %s' % str(linea_inicio)) linea_inicio = 0 if total_lineas != None and not isinstance(total_lineas, int): try: total_lineas = int(total_lineas) except: logger.error('Read: ERROR of total_lineas: %s' % str(total_lineas)) total_lineas = None if xbmc_vfs and vfs: if not exists(path): return False f = xbmcvfs.File(path, "rb") if linea_inicio > 0: if not isinstance(whence, int): try: whence = int(whence) except: return False f.seek(linea_inicio, whence) logger.debug('POSITION of beginning of reading,, tell(): %s' % f.seek(0, 1)) if total_lineas == None: total_lineas = 0 data = f.read(total_lineas) return "".join(data) elif path.lower().startswith("smb://"): f = samba.smb_open(path, "rb") else: f = open(path, "rb") data = [] for x, line in enumerate(f): if x < linea_inicio: continue if len(data) == total_lineas: break data.append(line) f.close() except: if not silent: logger.error("ERROR reading file: %s" % path) logger.error(traceback.format_exc()) return False else: if not PY3: return unicode("".join(data)) else: return unicode(b"".join(data))
def updateFromZip(message=config.get_localized_string(80050)): dp = platformtools.dialog_progress_bg(config.get_localized_string(20000), message) dp.update(0) remotefilename = 'https://github.com/' + user + "/" + repo + "/archive/" + branch + ".zip" localfilename = filetools.join(xbmc.translatePath("special://home/addons/"), "plugin.video.kod.update.zip") destpathname = xbmc.translatePath("special://home/addons/") extractedDir = filetools.join(destpathname, "addon-" + branch) logger.info("remotefilename=%s" % remotefilename) logger.info("localfilename=%s" % localfilename) logger.info('extract dir: ' + extractedDir) # pulizia preliminare remove(localfilename) removeTree(extractedDir) try: urllib.urlretrieve(remotefilename, localfilename, lambda nb, bs, fs, url=remotefilename: _pbhook(nb, bs, fs, url, dp)) except Exception as e: platformtools.dialog_ok(config.get_localized_string(20000), config.get_localized_string(80031)) logger.info('Non sono riuscito a scaricare il file zip') logger.info(e) dp.close() return False # Lo descomprime logger.info("decompressione...") logger.info("destpathname=%s" % destpathname) if os.path.isfile(localfilename): logger.info('il file esiste') dp.update(80, config.get_localized_string(20000), config.get_localized_string(80032)) import zipfile try: hash = fixZipGetHash(localfilename) logger.info(hash) with zipfile.ZipFile(fOpen(localfilename, 'rb')) as zip: size = sum([zinfo.file_size for zinfo in zip.filelist]) cur_size = 0 for member in zip.infolist(): zip.extract(member, destpathname) cur_size += member.file_size dp.update(int(80 + cur_size * 15 / size)) except Exception as e: logger.info('Non sono riuscito ad estrarre il file zip') logger.error(e) import traceback logger.error(traceback.print_exc()) dp.close() remove(localfilename) return False dp.update(95) # puliamo tutto global addonDir if extractedDir != addonDir: removeTree(addonDir) xbmc.sleep(1000) rename(extractedDir, 'plugin.video.kod') addonDir = filetools.join(destpathname, 'plugin.video.kod') logger.info("Cancellando il file zip...") remove(localfilename) dp.update(100) xbmc.sleep(1000) dp.close() xbmc.executebuiltin("UpdateLocalAddons") # in run() # refreshLang() return hash
def verify_directories_created(): from dependencies import logger, filetools, xbmc_videolibrary config_paths = [["videolibrarypath", "videolibrary"], ["downloadpath", "downloads"], ["downloadlistpath", "downloads/list"], ["settings_path", "settings_channels"]] for path, default in config_paths: saved_path = get_setting(path) # videoteca if path == "videolibrarypath": if not saved_path: saved_path = xbmc_videolibrary.search_library_path() if saved_path: set_setting(path, saved_path) if not saved_path: saved_path = "special://profile/addon_data/plugin.video." + PLUGIN_NAME + "/" + default set_setting(path, saved_path) saved_path = xbmc.translatePath(saved_path) if not filetools.exists(saved_path): logger.debug("Creating %s: %s" % (path, saved_path)) filetools.mkdir(saved_path) config_paths = [["folder_movies", "CINE"], ["folder_tvshows", "SERIES"]] for path, default in config_paths: saved_path = get_setting(path) if not saved_path: saved_path = default set_setting(path, saved_path) content_path = filetools.join(get_videolibrary_path(), saved_path) if not filetools.exists(content_path): logger.debug("Creating %s: %s" % (path, content_path)) # si se crea el directorio filetools.mkdir(content_path) from dependencies import xbmc_videolibrary xbmc_videolibrary.update_sources(get_setting("videolibrarypath")) xbmc_videolibrary.update_sources(get_setting("downloadpath")) try: from dependencies import scrapertools # Buscamos el archivo addon.xml del skin activo skindir = filetools.join(xbmc.translatePath("special://home"), 'addons', xbmc.getSkinDir(), 'addon.xml') if not os.path.isdir(skindir): return # No hace falta mostrar error en el log si no existe la carpeta # Extraemos el nombre de la carpeta de resolución por defecto folder = "" data = filetools.read(skindir) res = scrapertools.find_multiple_matches(data, '(<res .*?>)') for r in res: if 'default="true"' in r: folder = scrapertools.find_single_match(r, 'folder="([^"]+)"') break # Comprobamos si existe en el addon y sino es así, la creamos default = filetools.join(get_runtime_path(), 'resources', 'skins', 'Default') if folder and not filetools.exists(filetools.join(default, folder)): filetools.mkdir(filetools.join(default, folder)) # Copiamos el archivo a dicha carpeta desde la de 720p si éste no existe o si el tamaño es diferente if folder and folder != '720p': for root, folders, files in filetools.walk( filetools.join(default, '720p')): for f in files: if not filetools.exists(filetools.join(default, folder, f)) or \ (filetools.getsize(filetools.join(default, folder, f)) != filetools.getsize(filetools.join(default, '720p', f))): filetools.copy(filetools.join(default, '720p', f), filetools.join(default, folder, f), True) except: import traceback logger.error("Al comprobar o crear la carpeta de resolución") logger.error(traceback.format_exc())
def execute_sql_kodi(sql): """ Run sql query against kodi database @param sql: Valid sql query @type sql: str @return: Number of records modified or returned by the query @rtype nun_records: int @return: list with the query result @rtype records: list of tuples """ logger.info() file_db = "" nun_records = 0 records = None # We look for the archive of the video database according to the version of kodi video_db = config.get_platform(True)['video_db'] if video_db: file_db = filetools.join( xbmc.translatePath("special://userdata/Database"), video_db) # alternative method to locate the database if not file_db or not filetools.exists(file_db): file_db = "" for f in filetools.listdir( xbmc.translatePath("special://userdata/Database")): path_f = filetools.join( xbmc.translatePath("special://userdata/Database"), f) if filetools.isfile(path_f) and f.lower().startswith( 'myvideos') and f.lower().endswith('.db'): file_db = path_f break if file_db: logger.info("DB file: %s" % file_db) conn = None try: import sqlite3 conn = sqlite3.connect(file_db) cursor = conn.cursor() logger.info("Running sql: %s" % sql) cursor.execute(sql) conn.commit() records = cursor.fetchall() if sql.lower().startswith("select"): nun_records = len(records) if nun_records == 1 and records[0][0] is None: nun_records = 0 records = [] else: nun_records = conn.total_changes conn.close() logger.info("Query executed. Records: %s" % nun_records) except: logger.error("Error executing sql query") if conn: conn.close() else: logger.info("Database not found") return nun_records, records