def android_workaround(self, new_dest_path): ### Alfa (entera) for libname in get_libname(self.platform): libpath = filetools.join(self.dest_path, libname) size = str(filetools.getsize(libpath)) new_libpath = filetools.join(new_dest_path, libname) if filetools.exists(new_libpath): new_size = str(filetools.getsize(new_libpath)) if size != new_size: res = filetools.remove(new_libpath, su=True) if res: log('Deleted: (%s) %s -> (%s) %s' % (size, libpath, new_size, new_libpath)) if not filetools.exists(new_libpath): res = filetools.copy(libpath, new_libpath, ch_mod='777', su=True) ### ALFA else: log('Module exists. Not copied... %s' % new_libpath) ### ALFA return new_dest_path
def clean_db_cache(item): logger.info() import sqlite3, time from core import filetools fecha_caducidad = time.time() - (31 * 24 * 60 * 60) # al cabo de 31 días fname = filetools.join(config.get_data_path(), "tmdb.sqlite") conn = sqlite3.connect(fname) c = conn.cursor() c.execute('SELECT COUNT() FROM tmdb_cache') numregs = c.fetchone()[0] c.execute('SELECT COUNT() FROM tmdb_cache WHERE added < ?', (fecha_caducidad, )) numregs_expired = c.fetchone()[0] txt = 'El caché de Tmdb ocupa [COLOR gold]%s[/COLOR]' % config.format_bytes( filetools.getsize(fname)) txt += ' y contiene [COLOR gold]%s[/COLOR] registros.' % numregs txt += ' ¿ Borrar los [COLOR blue]%s[/COLOR] registros que tienen más de un mes de antiguedad ?' % numregs_expired if platformtools.dialog_yesno('Limpiar caché Tmdb', txt): c.execute('DELETE FROM tmdb_cache WHERE added < ?', (fecha_caducidad, )) conn.commit() conn.execute('VACUUM') platformtools.dialog_notification(config.__addon_name, 'Limpiado caché Tmdb', time=2000, sound=False) conn.close()
def set_watched(id): watched_file = dict() if filetools.exists(data_path) and filetools.getsize(data_path) > 0: watched_file = jsontools.load(filetools.read(data_path)) watched_file[id] = "true" filetools.write(data_path, jsontools.dump(watched_file))
def downloadbest(video_urls, title, continuar=False): logger.info() # Le da la vuelta, para poner el de más calidad primero ( list() es para que haga una copia ) invertida = list(video_urls) invertida.reverse() for elemento in invertida: # videotitle = elemento[0] url = elemento[1] logger.info("Descargando opción " + title + " " + url.encode('ascii', 'ignore')) # Calcula el fichero donde debe grabar try: fullpath = getfilefromtitle(url, title.strip()) # Si falla, es porque la URL no vale para nada except: import traceback logger.error(traceback.format_exc()) continue # Descarga try: ret = downloadfile(url, fullpath, continuar=continuar) # Llegados a este punto, normalmente es un timeout except urllib.error.URLError as e: import traceback logger.error(traceback.format_exc()) ret = -2 # El usuario ha cancelado la descarga if ret == -1: return -1 else: # El fichero ni siquiera existe if not filetools.exists(fullpath): logger.info( "-> No ha descargado nada, probando con la siguiente opción si existe" ) # El fichero existe else: tamanyo = filetools.getsize(fullpath) # Tiene tamaño 0 if tamanyo == 0: logger.info( "-> Descargado un fichero con tamaño 0, probando con la siguiente opción si existe" ) os.remove(fullpath) else: logger.info( "-> Descargado un fichero con tamaño %d, lo da por bueno" % tamanyo) return 0 return -2
def check_update(self): need_update=False for libname in get_libname(self.platform): if libname!='liblibtorrent.so': self.libpath = filetools.join(self.dest_path, libname) self.sizepath=filetools.join(self.root, self.platform['system'], self.platform['version'], libname+'.size.txt') size=str(filetools.getsize(self.libpath)) size_old=open( self.sizepath, "r" ).read() if size_old!=size: need_update=True return need_update
def downloadbest(video_urls, title, continuar=False): logger.info() # Flip it over, to put the highest quality one first (list () is for you to make a copy of) invertida = list(video_urls) invertida.reverse() for elemento in invertida: # videotitle = elemento[0] url = elemento[1] if not PY3: logger.info("Downloading option " + title + " " + url.encode('ascii', 'ignore')) else: logger.info("Downloading option " + title + " " + url.encode('ascii', 'ignore').decode('utf-8')) # Calculate the file where you should record try: fullpath = getfilefromtitle(url, title.strip()) # If it fails, it is because the URL is useless except: import traceback logger.error(traceback.format_exc()) continue # Descarga try: ret = downloadfile(url, fullpath, continuar=continuar) # At this point, it is usually a timeout. except urllib.error.URLError as e: import traceback logger.error(traceback.format_exc()) ret = -2 # The user has canceled the download if ret == -1: return -1 else: # EThe file doesn't even exist if not filetools.exists(fullpath): logger.info("-> You have not downloaded anything, testing with the following option if there is") # The file exists else: tamanyo = filetools.getsize(fullpath) # It has size 0 if tamanyo == 0: logger.info("-> Download a file with size 0, testing with the following option if it exists") os.remove(fullpath) else: logger.info("-> Download a file with size %d, he takes it for good" % tamanyo) return 0 return -2
def informacion_lista(item): logger.info() fullfilename = filetools.join(trackingtools.get_tracking_path(), item.lista) if not filetools.exists(fullfilename): platformtools.dialog_ok(config.__addon_name, 'Error, no se encuentra la lista!', item.lista) return False db = trackingtools.TrackingData(item.lista) count_movies = db.get_movies_count() count_shows = db.get_shows_count() count_episodes = db.get_episodes_count() db.close() txt = 'Nombre: [COLOR gold]%s[/COLOR]' % item.lista txt += '[CR][CR]Número de películas: [B]%d[/B]' % count_movies txt += '[CR][CR]Número de series: [B]%d[/B]' % count_shows txt += '[CR][CR]Número de episodios: [B]%d[/B]' % count_episodes txt += '[CR][CR]Tamaño de la base de datos: [B]%s[/B]' % config.format_bytes(filetools.getsize(fullfilename)) platformtools.dialog_textviewer('Información de la lista', txt) return True
def conf_tools(item): logger.info() # Activar o desactivar canales if item.extra == "channels_onoff": if config.get_platform( True )['num_version'] >= 17.0: # A partir de Kodi 16 se puede usar multiselect, y de 17 con preselect return channels_onoff(item) import channelselector from core import channeltools channel_list = channelselector.filterchannels("allchannelstatus") excluded_channels = [ 'url', 'search', 'videolibrary', 'setting', 'news', # 'help', 'downloads' ] list_controls = [] try: list_controls.append({ 'id': "all_channels", 'type': "list", 'label': config.get_localized_string(60594), 'default': 0, 'enabled': True, 'visible': True, 'lvalues': [ '', config.get_localized_string(60591), config.get_localized_string(60592), config.get_localized_string(60593) ] }) for channel in channel_list: # Si el canal esta en la lista de exclusiones lo saltamos if channel.channel not in excluded_channels: channel_parameters = channeltools.get_channel_parameters( channel.channel) status_control = "" status = config.get_setting("enabled", channel.channel) # si status no existe es que NO HAY valor en _data.json if status is None: status = channel_parameters["active"] logger.debug("%s | Status (XML): %s" % (channel.channel, status)) if not status: status_control = config.get_localized_string(60595) else: logger.debug("%s | Status: %s" % (channel.channel, status)) control = { 'id': channel.channel, 'type': "bool", 'label': channel_parameters["title"] + status_control, 'default': status, 'enabled': True, 'visible': True } list_controls.append(control) else: continue except: import traceback logger.error("Error: %s" % traceback.format_exc()) else: return platformtools.show_channel_settings( list_controls=list_controls, item=item.clone(channel_list=channel_list), caption=config.get_localized_string(60596), callback="channel_status", custom_button={"visible": False}) # Comprobacion de archivos channel_data.json elif item.extra == "lib_check_datajson": itemlist = [] import channelselector from core import channeltools channel_list = channelselector.filterchannels("allchannelstatus") # Tener una lista de exclusion no tiene mucho sentido por que se comprueba si channel.json tiene "settings", # pero por si acaso se deja excluded_channels = ['url', 'setting', 'help'] try: import os from core import jsontools for channel in channel_list: list_status = None default_settings = None # Se comprueba si el canal esta en la lista de exclusiones if channel.channel not in excluded_channels: # Se comprueba que tenga "settings", sino se salta list_controls, dict_settings = channeltools.get_channel_controls_settings( channel.channel) if not list_controls: itemlist.append( Item(channel=CHANNELNAME, title=channel.title + config.get_localized_string(60569), action="", folder=False, thumbnail=channel.thumbnail)) continue # logger.info(channel.channel + " SALTADO!") # Se cargan los ajustes del archivo json del canal file_settings = os.path.join( config.get_data_path(), "settings_channels", channel.channel + "_data.json") dict_settings = {} dict_file = {} if filetools.exists(file_settings): # logger.info(channel.channel + " Tiene archivo _data.json") channeljson_exists = True # Obtenemos configuracion guardada de ../settings/channel_data.json try: dict_file = jsontools.load( open(file_settings, "rb").read()) if isinstance(dict_file, dict) and 'settings' in dict_file: dict_settings = dict_file['settings'] except EnvironmentError: logger.error("ERROR al leer el archivo: %s" % file_settings) else: # logger.info(channel.channel + " No tiene archivo _data.json") channeljson_exists = False if channeljson_exists: try: datajson_size = filetools.getsize(file_settings) except: import traceback logger.error(channel.title + config.get_localized_string(60570) % traceback.format_exc()) else: datajson_size = None # Si el _data.json esta vacio o no existe... if (len(dict_settings) and datajson_size) == 0 or not channeljson_exists: # Obtenemos controles del archivo ../channels/channel.json needsfix = True try: # Se cargan los ajustes por defecto list_controls, default_settings = channeltools.get_channel_controls_settings( channel.channel) # logger.info(channel.title + " | Default: %s" % default_settings) except: import traceback logger.error(channel.title + config.get_localized_string(60570) % traceback.format_exc()) # default_settings = {} # Si _data.json necesita ser reparado o no existe... if needsfix or not channeljson_exists: if default_settings is not None: # Creamos el channel_data.json default_settings.update(dict_settings) dict_settings = default_settings dict_file['settings'] = dict_settings # Creamos el archivo ../settings/channel_data.json json_data = jsontools.dump(dict_file) try: open(file_settings, "wb").write(json_data) # logger.info(channel.channel + " - Archivo _data.json GUARDADO!") # El channel_data.json se ha creado/modificado list_status = config.get_localized_string( 60560) except EnvironmentError: logger.error( "ERROR al salvar el archivo: %s" % file_settings) else: if default_settings is None: list_status = config.get_localized_string( 60571) else: # logger.info(channel.channel + " - NO necesita correccion!") needsfix = False # Si se ha establecido el estado del canal se añade a la lista if needsfix is not None: if needsfix: if not channeljson_exists: list_status = config.get_localized_string( 60588) list_colour = "red" else: list_status = config.get_localized_string( 60589) list_colour = "green" else: # Si "needsfix" es "false" y "datjson_size" es None habra # ocurrido algun error if datajson_size is None: list_status = config.get_localized_string( 60590) list_colour = "red" else: list_status = config.get_localized_string( 60589) list_colour = "green" if list_status is not None: itemlist.append( Item(channel=CHANNELNAME, title=channel.title + list_status, action="", folder=False, thumbnail=channel.thumbnail, text_color=list_colour)) else: logger.error("Algo va mal con el canal %s" % channel.channel) # Si el canal esta en la lista de exclusiones lo saltamos else: continue except: import traceback logger.error("Error: %s" % traceback.format_exc()) return itemlist
def get_environment(): """ Devuelve las variables de entorno del OS, de Kodi y de Alfa más habituales, necesarias para el diagnóstico de fallos """ try: import base64 import ast environment = config.get_platform(full_version=True) environment['num_version'] = str(environment['num_version']) environment['python_version'] = '%s (%s, %s)' % (str(platform.python_version()), \ str(sys.api_version), str(platform.python_implementation())) environment['os_release'] = str(platform.release()) environment['prod_model'] = '' try: import multiprocessing environment['proc_num'] = ' (%sx)' % str( multiprocessing.cpu_count()) except: environment['proc_num'] = '' if xbmc.getCondVisibility("system.platform.Windows"): try: if platform.platform(): environment['os_release'] = str( platform.platform()).replace('Windows-', '') elif platform._syscmd_ver()[2]: environment['os_release'] = str(platform._syscmd_ver()[2]) command = ["wmic", "cpu", "get", "name"] p = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, creationflags=0x08000000) output_cmd, error_cmd = p.communicate() if PY3 and isinstance(output_cmd, bytes): output_cmd = output_cmd.decode() output_cmd = re.sub(r'\n|\r|\s{2}', '', output_cmd) environment['prod_model'] = str(scrapertools.find_single_match(output_cmd, \ '\w+.*?(?i)(?:Intel\(R\))?(?:\s*Core\(TM\))\s*(.*?CPU.*?)\s*(?:\@|$)')) except: pass if xbmc.getCondVisibility("system.platform.Android"): environment['os_name'] = 'Android' try: for label_a in subprocess.check_output('getprop').split(FF): if PY3 and isinstance(label_a, bytes): label_a = label_a.decode() if 'build.version.release' in label_a: environment['os_release'] = str( scrapertools.find_single_match( label_a, ':\s*\[(.*?)\]$')) if 'product.model' in label_a: environment['prod_model'] = str( scrapertools.find_single_match( label_a, ':\s*\[(.*?)\]$')) except: try: for label_a in filetools.read(os.environ['ANDROID_ROOT'] + '/build.prop').split(): if 'build.version.release' in label_a: environment['os_release'] = str( scrapertools.find_single_match( label_a, '=(.*?)$')) if 'product.model' in label_a: environment['prod_model'] = str( scrapertools.find_single_match( label_a, '=(.*?)$')) except: pass environment['prod_model'] += ' (%s)' % config.is_rooted( silent=True) elif xbmc.getCondVisibility("system.platform.Linux"): environment['os_name'] = 'Linux' try: for label_a in subprocess.check_output('hostnamectl').split( FF): if PY3 and isinstance(label_a, bytes): label_a = label_a.decode() if 'Operating' in label_a: environment['os_release'] = str( scrapertools.find_single_match( label_a, 'Operating\s*S\w+:\s*(.*?)\s*$')) break for label_a in subprocess.check_output( ['cat', '/proc/cpuinfo']).split(FF): if PY3 and isinstance(label_a, bytes): label_a = label_a.decode() if 'model name' in label_a: environment['prod_model'] = str(scrapertools.find_single_match(label_a, \ 'model.*?:\s*(?i)(?:Intel\(R\))?(?:\s*Core\(TM\))\s*(.*?CPU.*?)\s*(?:\@|$)')) break except: pass elif xbmc.getCondVisibility("system.platform.Linux.RaspberryPi"): environment['os_name'] = 'RaspberryPi' else: environment['os_name'] = str(platform.system()) if not environment['os_release']: environment['os_release'] = str(platform.release()) if environment['proc_num'] and environment['prod_model']: environment['prod_model'] += environment['proc_num'] environment['machine'] = str(platform.machine()) environment['architecture'] = str(sys.maxsize > 2**32 and "64-bit" or "32-bit") environment['language'] = str(xbmc.getInfoLabel('System.Language')) environment['cpu_usage'] = str(xbmc.getInfoLabel('System.CpuUsage')) environment['mem_total'] = str( xbmc.getInfoLabel('System.Memory(total)')).replace('MB', '').replace( 'KB', '') environment['mem_free'] = str( xbmc.getInfoLabel('System.Memory(free)')).replace('MB', '').replace( 'KB', '') if not environment['mem_total'] or not environment['mem_free']: try: if environment['os_name'].lower() == 'windows': kernel32 = ctypes.windll.kernel32 c_ulong = ctypes.c_ulong c_ulonglong = ctypes.c_ulonglong class MEMORYSTATUS(ctypes.Structure): _fields_ = [('dwLength', c_ulong), ('dwMemoryLoad', c_ulong), ('dwTotalPhys', c_ulonglong), ('dwAvailPhys', c_ulonglong), ('dwTotalPageFile', c_ulonglong), ('dwAvailPageFile', c_ulonglong), ('dwTotalVirtual', c_ulonglong), ('dwAvailVirtual', c_ulonglong), ('availExtendedVirtual', c_ulonglong)] memoryStatus = MEMORYSTATUS() memoryStatus.dwLength = ctypes.sizeof(MEMORYSTATUS) kernel32.GlobalMemoryStatus(ctypes.byref(memoryStatus)) environment['mem_total'] = str( old_div(int(memoryStatus.dwTotalPhys), (1024**2))) environment['mem_free'] = str( old_div(int(memoryStatus.dwAvailPhys), (1024**2))) else: with open('/proc/meminfo') as f: meminfo = f.read() environment['mem_total'] = str( old_div( int( re.search(r'MemTotal:\s+(\d+)', meminfo).groups()[0]), 1024)) environment['mem_free'] = str( old_div( int( re.search(r'MemAvailable:\s+(\d+)', meminfo).groups()[0]), 1024)) except: environment['mem_total'] = '' environment['mem_free'] = '' try: environment['kodi_buffer'] = '20' environment['kodi_bmode'] = '0' environment['kodi_rfactor'] = '4.0' if filetools.exists( filetools.join("special://userdata", "advancedsettings.xml")): advancedsettings = filetools.read( filetools.join("special://userdata", "advancedsettings.xml")).split('\n') for label_a in advancedsettings: if 'memorysize' in label_a: environment['kodi_buffer'] = str( old_div( int( scrapertools.find_single_match( label_a, '>(\d+)<\/')), 1024**2)) if 'buffermode' in label_a: environment['kodi_bmode'] = str( scrapertools.find_single_match( label_a, '>(\d+)<\/')) if 'readfactor' in label_a: environment['kodi_rfactor'] = str( scrapertools.find_single_match( label_a, '>(.*?)<\/')) except: pass environment['userdata_path'] = str(config.get_data_path()) environment['userdata_path_perm'] = filetools.file_info( environment['userdata_path']) if not environment['userdata_path_perm']: del environment['userdata_path_perm'] try: if environment['os_name'].lower() == 'windows': free_bytes = ctypes.c_ulonglong(0) ctypes.windll.kernel32.GetDiskFreeSpaceExW( ctypes.c_wchar_p(environment['userdata_path']), None, None, ctypes.pointer(free_bytes)) environment['userdata_free'] = str( round(float(free_bytes.value) / (1024**3), 3)) else: disk_space = os.statvfs(environment['userdata_path']) if not disk_space.f_frsize: disk_space.f_frsize = disk_space.f_frsize.f_bsize environment['userdata_free'] = str(round((float(disk_space.f_bavail) / \ (1024**3)) * float(disk_space.f_frsize), 3)) except: environment['userdata_free'] = '?' if environment['userdata_path_perm']: environment['userdata_path'] = environment['userdata_path_perm'] del environment['userdata_path_perm'] environment['torrent_lang'] = '%s/%s' % (config.get_setting("channel_language", default="").upper(), \ config.get_setting("second_language", default="").upper()) try: environment['videolab_series'] = '?' environment['videolab_episodios'] = '?' environment['videolab_pelis'] = '?' environment['videolab_path'] = str(config.get_videolibrary_path()) environment['videolab_path_perm'] = filetools.file_info( environment['videolab_path']) if not environment['videolab_path_perm']: environment['videolab_path_perm'] = environment[ 'videolab_path'] if filetools.exists(filetools.join(environment['videolab_path'], \ config.get_setting("folder_tvshows"))): environment['videolab_series'] = str(len(filetools.listdir(filetools.join(environment['videolab_path'], \ config.get_setting("folder_tvshows"))))) counter = 0 for root, folders, files in filetools.walk(filetools.join(environment['videolab_path'], \ config.get_setting("folder_tvshows"))): for file in files: if file.endswith('.strm'): counter += 1 environment['videolab_episodios'] = str(counter) if filetools.exists(filetools.join(environment['videolab_path'], \ config.get_setting("folder_movies"))): environment['videolab_pelis'] = str(len(filetools.listdir(filetools.join(environment['videolab_path'], \ config.get_setting("folder_movies"))))) except: pass try: video_updates = [ 'No', 'Inicio', 'Una vez', 'Inicio+Una vez', 'Dos veces al día' ] environment['videolab_update'] = str( video_updates[config.get_setting("update", "videolibrary")]) except: environment['videolab_update'] = '?' try: if environment['os_name'].lower() == 'windows': free_bytes = ctypes.c_ulonglong(0) ctypes.windll.kernel32.GetDiskFreeSpaceExW( ctypes.c_wchar_p(environment['videolab_path']), None, None, ctypes.pointer(free_bytes)) environment['videolab_free'] = str( round(float(free_bytes.value) / (1024**3), 3)) else: disk_space = os.statvfs(environment['videolab_path']) if not disk_space.f_frsize: disk_space.f_frsize = disk_space.f_frsize.f_bsize environment['videolab_free'] = str(round((float(disk_space.f_bavail) / \ (1024**3)) * float(disk_space.f_frsize), 3)) except: environment['videolab_free'] = '?' environment['torrent_list'] = [] environment['torrentcli_option'] = '' environment['torrent_error'] = '' environment['torrentcli_rar'] = config.get_setting("mct_rar_unpack", server="torrent", default=True) environment['torrentcli_backgr'] = config.get_setting( "mct_background_download", server="torrent", default=True) environment['torrentcli_lib_path'] = config.get_setting( "libtorrent_path", server="torrent", default="") if environment['torrentcli_lib_path']: lib_path = 'Activo' else: lib_path = 'Inactivo' if config.get_setting("libtorrent_version", server="torrent", default=""): lib_path += '-%s' % config.get_setting( "libtorrent_version", server="torrent", default="") environment['torrentcli_unrar'] = config.get_setting("unrar_path", server="torrent", default="") if environment['torrentcli_unrar']: if xbmc.getCondVisibility("system.platform.Android"): unrar = 'Android' else: unrar = filetools.dirname(environment['torrentcli_unrar']) unrar = filetools.basename(unrar).capitalize() else: unrar = 'Inactivo' torrent_id = config.get_setting("torrent_client", server="torrent", default=0) environment['torrentcli_option'] = str(torrent_id) torrent_options = platformtools.torrent_client_installed() if lib_path != 'Inactivo': torrent_options = ['MCT'] + torrent_options torrent_options = ['BT'] + torrent_options environment['torrent_list'].append({'Torrent_opt': str(torrent_id), 'Libtorrent': lib_path, \ 'RAR_Auto': str(environment['torrentcli_rar']), \ 'RAR_backgr': str(environment['torrentcli_backgr']), \ 'UnRAR': unrar}) environment['torrent_error'] = config.get_setting("libtorrent_error", server="torrent", default="") if environment['torrent_error']: environment['torrent_list'].append( {'Libtorrent_error': environment['torrent_error']}) for torrent_option in torrent_options: cliente = dict() cliente['D_load_Path'] = '' cliente['Libre'] = '?' cliente['Plug_in'] = torrent_option.replace('Plugin externo: ', '') if cliente['Plug_in'] == 'BT': cliente['D_load_Path'] = str( config.get_setting("bt_download_path", server="torrent", default='')) if not cliente['D_load_Path']: continue cliente['D_load_Path'] = filetools.join( cliente['D_load_Path'], 'BT-torrents') cliente['D_load_Path_perm'] = filetools.file_info( cliente['D_load_Path']) if not cliente['D_load_Path_perm']: del cliente['D_load_Path_perm'] cliente['Buffer'] = str( config.get_setting("bt_buffer", server="torrent", default=50)) elif cliente['Plug_in'] == 'MCT': cliente['D_load_Path'] = str( config.get_setting("mct_download_path", server="torrent", default='')) if not cliente['D_load_Path']: continue cliente['D_load_Path'] = filetools.join( cliente['D_load_Path'], 'MCT-torrent-videos') cliente['D_load_Path_perm'] = filetools.file_info( cliente['D_load_Path']) if not cliente['D_load_Path_perm']: del cliente['D_load_Path_perm'] cliente['Buffer'] = str( config.get_setting("mct_buffer", server="torrent", default=50)) elif xbmc.getCondVisibility('System.HasAddon("plugin.video.%s")' % cliente['Plug_in']): try: __settings__ = xbmcaddon.Addon(id="plugin.video.%s" % cliente['Plug_in']) except: continue cliente['Plug_in'] = cliente['Plug_in'].capitalize() if cliente['Plug_in'] == 'Torrenter': cliente['D_load_Path'] = str( filetools.translatePath( __settings__.getSetting('storage'))) if not cliente['D_load_Path']: cliente['D_load_Path'] = str(filetools.join("special://home/", \ "cache", "xbmcup", "plugin.video.torrenter", "Torrenter")) cliente['D_load_Path_perm'] = filetools.file_info( cliente['D_load_Path']) if not cliente['D_load_Path_perm']: del cliente['D_load_Path_perm'] cliente['Buffer'] = str( __settings__.getSetting('pre_buffer_bytes')) else: cliente['D_load_Path'] = str( filetools.translatePath( __settings__.getSetting('download_path'))) cliente['D_load_Path_perm'] = filetools.file_info( cliente['D_load_Path']) if not cliente['D_load_Path_perm']: del cliente['D_load_Path_perm'] cliente['Buffer'] = str( __settings__.getSetting('buffer_size')) if __settings__.getSetting( 'download_storage' ) == '1' and __settings__.getSetting('memory_size'): cliente['Memoria'] = str( __settings__.getSetting('memory_size')) if cliente['D_load_Path']: try: if environment['os_name'].lower() == 'windows': free_bytes = ctypes.c_ulonglong(0) ctypes.windll.kernel32.GetDiskFreeSpaceExW( ctypes.c_wchar_p(cliente['D_load_Path']), None, None, ctypes.pointer(free_bytes)) cliente['Libre'] = str(round(float(free_bytes.value) / \ (1024**3), 3)).replace('.', ',') else: disk_space = os.statvfs(cliente['D_load_Path']) if not disk_space.f_frsize: disk_space.f_frsize = disk_space.f_frsize.f_bsize cliente['Libre'] = str(round((float(disk_space.f_bavail) / \ (1024**3)) * float(disk_space.f_frsize), 3)).replace('.', ',') except: pass if cliente['D_load_Path_perm']: cliente['D_load_Path'] = cliente['D_load_Path_perm'] del cliente['D_load_Path_perm'] environment['torrent_list'].append(cliente) environment['proxy_active'] = '' try: proxy_channel_bloqued_str = base64.b64decode( config.get_setting('proxy_channel_bloqued')).decode('utf-8') proxy_channel_bloqued = dict() proxy_channel_bloqued = ast.literal_eval(proxy_channel_bloqued_str) for channel_bloqued, proxy_active in list( proxy_channel_bloqued.items()): if proxy_active != 'OFF': environment['proxy_active'] += channel_bloqued + ', ' except: pass if not environment['proxy_active']: environment['proxy_active'] = 'OFF' environment['proxy_active'] = environment['proxy_active'].rstrip(', ') for root, folders, files in filetools.walk("special://logpath/"): for file in files: if file.lower() in ['kodi.log', 'jarvis.log', 'spmc.log', 'cemc.log', \ 'mygica.log', 'wonderbox.log', 'leiapp,log', \ 'leianmc.log', 'kodiapp.log', 'anmc.log', \ 'latin-anmc.log']: environment['log_path'] = str(filetools.join(root, file)) break else: environment['log_path'] = '' break if environment['log_path']: environment['log_size_bytes'] = str( filetools.getsize(environment['log_path'])) environment['log_size'] = str(round(float(environment['log_size_bytes']) / \ (1024*1024), 3)) else: environment['log_size_bytes'] = '' environment['log_size'] = '' environment['debug'] = str(config.get_setting('debug')) environment['addon_version'] = '%s (Upd: %s h.)' % (str(config.get_addon_version()), \ str(config.get_setting("addon_update_timer", default=12)).replace('0', 'No')) environment['assistant_version'] = str(None) if filetools.exists( filetools.join(config.get_data_path(), 'alfa-mobile-assistant.version')): environment['assistant_version'] = filetools.read( filetools.join(config.get_data_path(), 'alfa-mobile-assistant.version')) environment['assistant_cf_ua'] = str( config.get_setting('cf_assistant_ua', None)) except: logger.error(traceback.format_exc()) environment = {} environment['log_size'] = '' environment['cpu_usage'] = '' environment['python_version'] = '' environment['log_path'] = '' environment['userdata_free'] = '' environment['mem_total'] = '' environment['machine'] = '' environment['platform'] = '' environment['videolab_path'] = '' environment['num_version'] = '' environment['os_name'] = '' environment['video_db'] = '' environment['userdata_path'] = '' environment['log_size_bytes'] = '' environment['name_version'] = '' environment['language'] = '' environment['mem_free'] = '' environment['prod_model'] = '' environment['proxy_active'] = '' environment['architecture'] = '' environment['os_release'] = '' environment['videolab_free'] = '' environment['kodi_buffer'] = '' environment['kodi_bmode'] = '' environment['kodi_rfactor'] = '' environment['videolab_series'] = '' environment['videolab_episodios'] = '' environment['videolab_pelis'] = '' environment['videolab_update'] = '' environment['videolab_path_perm'] = '' environment['debug'] = '' environment['addon_version'] = '' environment['torrent_list'] = [] environment['torrent_lang'] = '' environment['torrentcli_option'] = '' environment['torrentcli_rar'] = '' environment['torrentcli_lib_path'] = '' environment['torrentcli_unrar'] = '' environment['torrent_error'] = '' environment['assistant_version'] = '' environment['assistant_cf_ua'] = '' return environment
def report_send(item, description=False, fatal=False): try: requests_status = True import requests except: requests_status = False logger.error(traceback.format_exc()) # Esta función realiza la operación de upload del LOG. El tamaño del archivo es de gran importacia porque # los servicios de "pastebin" gratuitos tienen limitaciones, a veces muy bajas. # Hay un servicio, File.io, que permite subida directa de "archivos binarios" a través de la función "request" # Esto aumenta drásticamente la capacidad del envío del log, muy por encima de lo necesitado # Por ello es necesario contar con una lista de servicios "pastebin" que puedan realizar la operación de upload, # ya sea por capacidad disponible o por disponibilidad. # Para poder usar los servidores "pastebin" con un código común, se ha creado un diccionario con los servidores # y sus características. En cada entrada se recogen las peculiaridades de cada servidor, tanto para formar # la petición consu POST como para la forma de recibir el código del upload en la respuesta (json, header, regex # en datos,...). # Al iniciar este método se aleatoriza la lista de servidores "pastebin" para evitar que todos los usuarios hagan # uploads contra el mismo servidor y puedan ocasionar sobrecargas. # Se lee el arcivo de log y se compara su tamaño con la capacidad del servidor (parámetro 10 de cada entrada # (empezando desde 0), expresado en MB, hasta que se encuentra uno capacitado. Si el upload falla se sigue intentado # con los siguientes servidores que tengan la capacidad requerida. # Si no se encuentra ningún servidor disponible se pide al usuario que lo intente más tarde, o que suba el log # directamente en el foro. Si es un problema de tamaño, se le pide que reicinie Kodi y reproduzca el fallo, para # que el LOG sea más pequeño. pastebin_list = { 'hastebin': { 'active': True, 'host': 'https://hastebin.com/', 'api_suffix': 'documents', 'filename': 'random', 'post_data_1': '', 'post_data_2': '', 'method': 'data', 'response_type': 'json', 'response_key': 'key', 'tag': '', 'max_size_mb': 0.29, 'timeout': 10, 'random_headers': True, 'host_return': 'raw/', 'host_return_tail': '', 'headers': '' }, 'dpaste': { 'active': True, 'host': 'http://dpaste.com/', 'api_suffix': 'api/v2/', 'filename': 'random', 'post_data_1': 'content=', 'post_data_2': '&syntax=text&title=%s&poster=alfa&expiry_days=7', 'method': 'headers', 'response_type': '', 'response_key': '', 'tag': 'location', 'max_size_mb': 0.23, 'timeout': 15, 'random_headers': True, 'host_return': '', 'host_return_tail': '.txt', 'headers': '' }, 'ghostbin': { 'active': True, 'host': 'https://ghostbin.com/', 'api_suffix': 'new', 'filename': 'random', 'post_data_1': 'lang=text&text=', 'post_data_2': '&expire=2d&password=&title=%s', 'method': 'data', 'response_type': 'regex', 'response_key': '<h4\s*style=[^>]+>[^<]*(?:<[^>]+>)?\s*<a\s*href="\/?([^"]+)"', 'tag': '', 'max_size_mb': 99.9, 'timeout': 15, 'random_headers': True, 'host_return': '', 'host_return_tail': '', 'headers': '' }, 'write.as': { 'active': True, 'host': 'https://write.as/', 'api_suffix': 'api/posts', 'filename': 'random', 'post_data_1': 'body=', 'post_data_2': '&title=%s', 'method': 'data', 'response_type': 'json', 'response_key': 'data', 'tag': 'id', 'max_size_mb': 0.018, 'timeout': 15, 'random_headers': True, 'host_return': '', 'host_return_tail': '', 'headers': '' }, 'controlc': { 'active': False, 'host': 'https://controlc.com/', 'api_suffix': 'index.php?act=submit', 'filename': 'random', 'post_data_1': 'input_text=', 'post_data_2': '&subdomain=&antispam=1&website=×tamp=&paste_password=&code=0&paste_title=%s', 'method': 'data', 'response_type': 'regex', 'response_key': '<h3>\s*<a\s*href="([^"]+)"', 'tag': '', 'max_size_mb': 99.0, 'timeout': 5, 'random_headers': True, 'host_return': '', 'host_return_tail': '', 'headers': '' }, 'bpaste': { 'active': True, 'host': 'https://bpa.st/', 'api_suffix': '', 'filename': 'random', 'post_data_1': 'code=', 'post_data_2': '&lexer=text&expiry=1week', 'method': 'data', 'response_type': 'regex', 'response_key': 'View\s*<a\s*href="[^*]+/(.*?)">raw<\/a>', 'tag': '', 'max_size_mb': 0.25, 'timeout': 15, 'random_headers': True, 'host_return': 'raw/', 'host_return_tail': '', 'headers': '' }, 'dumpz': { 'active': False, 'host': 'https://dumpz.org/', 'api_suffix': 'api/dump', 'filename': 'random', 'post_data_1': 'code=', 'post_data_2': '&lexer=text&comment=%s&password='******'method': 'headers', 'response_type': '', 'response_key': '', 'tag': 'location', 'max_size_mb': 0.99, 'timeout': 15, 'random_headers': True, 'host_return': '', 'host_return_tail': '', 'headers': '' }, 'file.io': { 'active': True, 'host': 'https://file.io/', 'api_suffix': '', 'filename': 'random', 'post_data_1': '', 'post_data_2': 'expires=1w', 'method': 'requests', 'response_type': 'json', 'response_key': 'key', 'tag': '', 'max_size_mb': 99.0, 'timeout': 30, 'random_headers': True, 'host_return': '', 'host_return_tail': '', 'headers': '' }, 'uploadfiles': { 'active': False, 'host': 'https://up.ufile.io/v1/upload', 'api_suffix': '', 'filename': 'random', 'post_data_1': '', 'post_data_2': '', 'method': 'curl', 'response_type': 'json', 'response_key': 'url', 'tag': '', 'max_size_mb': 99.0, 'timeout': 30, 'random_headers': True, 'host_return': None, 'host_return_tail': '', 'headers': { 'Referer': 'https://ufile.io/' } }, 'anonfiles': { 'active': True, 'host': 'https://api.anonfiles.com/upload', 'api_suffix': 'upload', 'filename': 'random', 'post_data_1': '', 'post_data_2': '', 'method': 'requests', 'response_type': 'json', 'response_key': 'data', 'tag': 'file,url,short', 'max_size_mb': 99.0, 'timeout': 30, 'random_headers': False, 'host_return': None, 'host_return_tail': '', 'headers': '' }, } pastebin_list_last = ['ghostbin', 'hastebin', 'file.io'] # Estos servicios los dejamos los últimos pastebin_one_use = ['file.io'] # Servidores de un solo uso y se borra pastebin_dir = [] paste_file = {} paste_params = () paste_post = '' status = False msg = 'Servicio no disponible. Inténtelo más tarde' # De cada al futuro se permitira al usuario que introduzca una breve descripción del fallo que se añadirá al LOG if description: description = platformtools.dialog_input( '', 'Introduzca una breve descripción del fallo') # Escribimos en el log algunas variables de Kodi y Alfa que nos ayudarán en el diagnóstico del fallo proxytools.logger_disp(debugging=True) environment = envtal.list_env() if not environment['log_path']: if filetools.exists(filetools.join("special://logpath/", 'kodi.log')): environment['log_path'] = str( filetools.join("special://logpath/", 'kodi.log')) else: environment['log_path'] = str( filetools.join("special://logpath/", 'xbmc.log')) environment['log_size_bytes'] = str( filetools.getsize(environment['log_path'])) environment['log_size'] = str( round(float(environment['log_size_bytes']) / (1024 * 1024), 3)) # Se lee el archivo de LOG log_path = environment['log_path'] if filetools.exists(log_path): log_size_bytes = int( environment['log_size_bytes']) # Tamaño del fichero en Bytes log_size = float(environment['log_size']) # Tamaño del fichero en MB log_data = filetools.read(log_path) # Datos del archivo if not log_data: # Algún error? platformtools.dialog_notification( 'No se puede leer el log de Kodi', 'Comuniquelo directamente en el Foro de Alfa') return else: # Log no existe o path erroneo? platformtools.dialog_notification( 'LOG de Kodi no encontrado', 'Comuniquelo directamente en el Foro de Alfa') return # Si se ha introducido la descripción del fallo, se inserta la principio de los datos del LOG log_title = '***** DESCRIPCIÓN DEL FALLO *****' if description: log_data = '%s\n%s\n\n%s' % (log_title, description, log_data) # Se aleatorizan los nombre de los servidores "pastebin" for label_a, value_a in list(pastebin_list.items()): if label_a not in pastebin_list_last: pastebin_dir.append(label_a) random.shuffle(pastebin_dir) pastebin_dir.extend( pastebin_list_last) # Estos servicios los dejamos los últimos # pastebin_dir = ['ghostbin'] # Para pruebas de un servicio # log_data = 'TEST PARA PRUEBAS DEL SERVICIO' # Se recorre la lista de servidores "pastebin" hasta localizar uno activo, con capacidad y disponibilidad for paste_name in pastebin_dir: paste_service = pastebin_list[paste_name] if not paste_service[ 'active']: # Si no esta activo el servidor, pasamos continue if paste_service[ 'method'] == 'requests' and not requests_status: # Si "requests" no esta activo, pasamos continue paste_host = paste_service['host'] # URL del servidor "pastebin" paste_sufix = paste_service[ 'api_suffix'] # sufijo del API para el POST paste_title = '' if paste_service['filename'] == 'random': paste_title = "LOG" + str(random.randrange( 1, 999999999)) # Título del LOG paste_post1 = paste_service['post_data_1'] # Parte inicial del POST paste_post2 = paste_service['post_data_2'] # Parte secundaria del POST paste_type = paste_service[ 'method'] # Tipo de downloadpage: REQUESTS, DATA o HEADERS paste_resp = paste_service[ 'response_type'] # Tipo de respuesta: JSON o datos con REGEX paste_resp_key = paste_service[ 'response_key'] # Si es JSON, etiqueta primaria con la CLAVE paste_url = paste_service[ 'tag'] # Etiqueta primaria para HEADER y sec. para JSON paste_file_size = paste_service[ 'max_size_mb'] # Capacidad en MB del servidor if paste_file_size > 0: # Si es 0, la capacidad es ilimitada if log_size > paste_file_size: # Verificación de capacidad y tamaño msg = 'Archivo de log demasiado grande. Reinicie Kodi y reinténtelo' continue paste_timeout = paste_service['timeout'] # Timeout para el servidor paste_random_headers = paste_service[ 'random_headers'] # Utiliza RANDOM headers para despistar el srv? paste_host_return = paste_service[ 'host_return'] # Parte de url para componer la clave para usuario paste_host_return_tail = paste_service[ 'host_return_tail'] # Sufijo de url para componer la clave para usuario paste_headers = {} if paste_service['headers']: # Headers requeridas por el servidor paste_headers.update(paste_service['headers']) if paste_name in pastebin_one_use: pastebin_one_use_msg = '[COLOR red]NO ACCEDA al INFORME: se BORRARÁ[/COLOR]' item.one_use = True else: pastebin_one_use_msg = '' try: # Se crea el POST con las opciones del servidor "pastebin" # Se trata el formato de "requests" if paste_type in ['requests', 'curl']: paste_file = {'file': (paste_title + '.log', log_data)} if paste_post1: paste_file.update(paste_post1) if paste_post2: if '%s' in paste_post2: paste_params = paste_post2 % (paste_title + '.log', log_size_bytes) else: paste_params = paste_post2 # Se trata el formato de downloads else: # log_data = 'Test de Servidor para ver su viabilidad (áéíóúñ¿?)' if paste_name in [ 'hastebin' ]: # Hay algunos servicios que no necesitan "quote" paste_post = log_data else: paste_post = urllib.quote_plus( log_data) # Se hace un "quote" de los datos del LOG if paste_post1: paste_post = '%s%s' % (paste_post1, paste_post) if paste_post2: if '%s' in paste_post2: paste_post += paste_post2 % paste_title else: paste_post += paste_post2 # Se hace la petición en downloadpage con HEADERS o DATA, con los parámetros del servidor if paste_type in ['data', 'headers']: data = httptools.downloadpage( paste_host + paste_sufix, post=paste_post, timeout=paste_timeout, random_headers=paste_random_headers, headers=paste_headers) data = data.data if paste_type == 'data' else data.headers # Si la petición es con formato REQUESTS, se realiza aquí elif paste_type == 'requests': # data = requests.post(paste_host, params=paste_params, files=paste_file, # timeout=paste_timeout) data = httptools.downloadpage( paste_host, params=paste_params, file=log_data, file_name=paste_title + '.log', timeout=paste_timeout, random_headers=paste_random_headers, headers=paste_headers) elif paste_type == 'curl': paste_sufix = '/create_session' data_post = {'file_size': len(log_data)} data = httptools.downloadpage( paste_host + paste_sufix, params=paste_params, ignore_response_code=True, post=data_post, timeout=paste_timeout, alfa_s=True, random_headers=paste_random_headers, headers=paste_headers).data data = jsontools.load(data) if not data.get("fuid", ""): logger.error("fuid: %s" % str(data)) raise fuid = data["fuid"] paste_sufix = '/chunk' log_data_chunks = log_data i = 0 chunk_len = 1024 while len(log_data_chunks) > 0: i += 1 chunk = log_data_chunks[:chunk_len] log_data_chunks = log_data_chunks[chunk_len:] data_post = {'fuid': fuid, 'chunk_index': i} data = httptools.downloadpage( paste_host + paste_sufix, params=paste_params, file=chunk, alfa_s=True, ignore_response_code=True, post=data_post, timeout=paste_timeout, CF_test=False, random_headers=paste_random_headers, headers=paste_headers).data if not 'successful' in data: logger.error("successful: %s" % str(data)) raise data = {} paste_sufix = '/finalise' data_post = { 'fuid': fuid, 'total_chunks': i, 'file_name': paste_title + '.log', 'file_type': 'doc' } resp = httptools.downloadpage( paste_host + paste_sufix, params=paste_params, ignore_response_code=True, post=data_post, timeout=paste_timeout, random_headers=paste_random_headers, headers=paste_headers) if not resp.data: logger.error("resp.content: %s" % str(resp.data)) raise data['data'] = resp.data data = type('HTTPResponse', (), data) except: msg = 'Inténtelo más tarde' logger.error('Fallo al guardar el informe. ' + msg) logger.error(traceback.format_exc()) continue # Se analiza la respuesta del servidor y se localiza la clave del upload para formar la url a pasar al usuario if data: paste_host_resp = paste_host if paste_host_return == None: # Si devuelve la url completa, no se compone paste_host_resp = '' paste_host_return = '' # Respuestas a peticiones REQUESTS key = '' if paste_type in ['requests', 'curl' ]: # Respuesta de petición tipo "requests"? if paste_resp == 'json': # Respuesta en formato JSON? if paste_resp_key in data.data: key = jsontools.load(data.data)[paste_resp_key] if paste_url and key: # hay etiquetas adicionales? try: for key_part in paste_url.split(','): key = key[ key_part] # por cada etiqueta adicional except: key = '' if key: item.url = "%s%s%s" % (paste_host_resp + paste_host_return, key, paste_host_return_tail) if not key: logger.error( 'ERROR en formato de retorno de datos. data.data=' + str(data.data)) continue # Respuestas a peticiones DOWNLOADPAGE elif paste_resp == 'json': # Respuesta en formato JSON? if paste_resp_key in data: if not paste_url: key = jsontools.load(data)[ paste_resp_key] # con una etiqueta else: key = jsontools.load(data)[paste_resp_key][ paste_url] # con dos etiquetas anidadas item.url = "%s%s%s" % (paste_host_resp + paste_host_return, key, paste_host_return_tail) else: logger.error( 'ERROR en formato de retorno de datos. data=' + str(data)) continue elif paste_resp == 'regex': # Respuesta en DATOS, a buscar con un REGEX? key = scrapertools.find_single_match(data, paste_resp_key) if key: item.url = "%s%s%s" % (paste_host_resp + paste_host_return, key, paste_host_return_tail) else: logger.error( 'ERROR en formato de retorno de datos. data=' + str(data)) continue elif paste_type == 'headers': # Respuesta en HEADERS, a buscar en "location"? if paste_url in data: item.url = data[ paste_url] # Etiqueta de retorno de la clave item.url = urlparse.urljoin( paste_host_resp + paste_host_return, item.url + paste_host_return_tail) else: logger.error( 'ERROR en formato de retorno de datos. response.headers=' + str(data)) continue else: logger.error( 'ERROR en formato de retorno de datos. paste_type=' + str(paste_type) + ' / DATA: ' + data) continue status = True # Operación de upload terminada con éxito logger.info( 'Reporte de error creado con exito: ' + str(item.url)) # Se guarda la URL del informe a usuario if fatal: # De uso futuro, para logger.crash platformtools.dialog_notification( 'Reporte de error creado con exito', 'Repórtelo en el foro agregando ERROR FATAL y esta URL: ') else: # Se pasa la URL del informe a usuario platformtools.dialog_notification( 'Reporte de error creado con exito', 'Repórtelo en el foro agregando una descripcion del fallo y esta URL: ' ) break # Operación terminado, no seguimos buscando if not status and not fatal: # Operación fracasada... platformtools.dialog_notification('Fallo al guardar el informe', msg) # ... se notifica la causa logger.error('Fallo al guardar el informe. ' + msg) channel_custom = os.path.join(config.get_runtime_path(), 'channels', 'custom.py') if not filetools.exists(channel_custom): config.set_setting("debug", False) config.set_setting("report_started", False) return item
def conf_tools(item): logger.info() # Activar o desactivar canales if item.extra == "channels_onoff": import channelselector from core import channeltools channel_list = channelselector.filterchannels("allchannelstatus") excluded_channels = ['tengourl', 'buscador', 'biblioteca', 'configuracion', 'novedades', 'personal', 'ayuda', 'descargas'] list_controls = [] try: list_controls.append({'id': "all_channels", 'type': "list", 'label': "Todos los canales", 'default': 0, 'enabled': True, 'visible': True, 'lvalues': ['', 'Activar todos', 'Desactivar todos', 'Establecer estado por defecto']}) for channel in channel_list: # Si el canal esta en la lista de exclusiones lo saltamos if channel.channel not in excluded_channels: channel_parameters = channeltools.get_channel_parameters(channel.channel) status_control = "" status = config.get_setting("enabled", channel.channel) # si status no existe es que NO HAY valor en _data.json if status is None: status = channel_parameters["active"] logger.debug("%s | Status (XML): %s" % (channel.channel, status)) if not status: status_control = " [COLOR grey](Desactivado por defecto)[/COLOR]" else: logger.debug("%s | Status: %s" % (channel.channel, status)) control = {'id': channel.channel, 'type': "bool", 'label': channel_parameters["title"] + status_control, 'default': status, 'enabled': True, 'visible': True} list_controls.append(control) else: continue except: import traceback logger.error("Error: %s" % traceback.format_exc()) else: return platformtools.show_channel_settings(list_controls=list_controls, item=item.clone(channel_list=channel_list), caption="Canales", callback="channel_status", custom_button={"visible": False}) # Comprobacion de archivos channel_data.json elif item.extra == "lib_check_datajson": itemlist = [] import channelselector from core import channeltools channel_list = channelselector.filterchannels("allchannelstatus") # Tener una lista de exclusion no tiene mucho sentido por que se comprueba si # el xml tiene "settings", pero por si acaso se deja excluded_channels = ['tengourl', 'configuracion', 'personal', 'ayuda'] try: import os from core import jsontools for channel in channel_list: list_status = None default_settings = None # Se comprueba si el canal esta en la lista de exclusiones if channel.channel not in excluded_channels: # Se comprueba que tenga "settings", sino se salta jsonchannel = channeltools.get_channel_json(channel.channel) if not jsonchannel.get("settings"): itemlist.append(Item(channel=CHANNELNAME, title=channel.title + " - No tiene ajustes por defecto", action="", folder=False, thumbnail=channel.thumbnail)) continue # logger.info(channel.channel + " SALTADO!") # Se cargan los ajustes del archivo json del canal file_settings = os.path.join(config.get_data_path(), "settings_channels", channel.channel + "_data.json") dict_settings = {} dict_file = {} if filetools.exists(file_settings): # logger.info(channel.channel + " Tiene archivo _data.json") channeljson_exists = True # Obtenemos configuracion guardada de ../settings/channel_data.json try: dict_file = jsontools.load_json(open(file_settings, "rb").read()) if isinstance(dict_file, dict) and 'settings' in dict_file: dict_settings = dict_file['settings'] except EnvironmentError: logger.error("ERROR al leer el archivo: %s" % file_settings) else: # logger.info(channel.channel + " No tiene archivo _data.json") channeljson_exists = False if channeljson_exists == True: try: datajson_size = filetools.getsize(file_settings) except: import traceback logger.error(channel.title + " | Detalle del error: %s" % traceback.format_exc()) else: datajson_size = None # Si el _data.json esta vacio o no existe... if (len(dict_settings) and datajson_size) == 0 or channeljson_exists == False: # Obtenemos controles del archivo ../channels/channel.xml needsfix = True try: # Se cargan los ajustes por defecto list_controls, default_settings = channeltools.get_channel_controls_settings(channel.channel) # logger.info(channel.title + " | Default: %s" % default_settings) except: import traceback logger.error(channel.title + " | Detalle del error: %s" % traceback.format_exc()) # default_settings = {} # Si _data.json necesita ser reparado o no existe... if needsfix == True or channeljson_exists == False: if default_settings is not None: # Creamos el channel_data.json default_settings.update(dict_settings) dict_settings = default_settings dict_file['settings'] = dict_settings # Creamos el archivo ../settings/channel_data.json json_data = jsontools.dump_json(dict_file) try: open(file_settings, "wb").write(json_data) # logger.info(channel.channel + " - Archivo _data.json GUARDADO!") # El channel_data.json se ha creado/modificado list_status = " - [COLOR red] CORREGIDO!![/COLOR]" except EnvironmentError: logger.error("ERROR al salvar el archivo: %s" % file_settings) else: if default_settings is None: list_status = " - [COLOR red] Imposible cargar los ajustes por defecto![/COLOR]" else: # logger.info(channel.channel + " - NO necesita correccion!") needsfix = False # Si se ha establecido el estado del canal se añade a la lista if needsfix is not None: if needsfix == True: if channeljson_exists == False: list_status = " - Ajustes creados" list_colour = "red" else: list_status = " - No necesita corrección" list_colour = "green" else: # Si "needsfix" es "false" y "datjson_size" es None habra # ocurrido algun error if datajson_size is None: list_status = " - Ha ocurrido algun error" list_colour = "red" else: list_status = " - No necesita corrección" list_colour = "green" if list_status is not None: itemlist.append(Item(channel=CHANNELNAME, title=channel.title + list_status, action="", folder=False, thumbnail=channel.thumbnail, text_color=list_colour)) else: logger.error("Algo va mal con el canal %s" % channel.channel) # Si el canal esta en la lista de exclusiones lo saltamos else: continue except: import traceback logger.error("Error: %s" % traceback.format_exc()) return itemlist
def downloadfile(url, nombrefichero, headers=None, silent=False, continuar=False, resumir=True): logger.info("url=" + url) logger.info("filename=" + nombrefichero) if headers is None: headers = [] progreso = None if config.is_xbmc() and nombrefichero.startswith("special://"): import xbmc nombrefichero = xbmc.translatePath(nombrefichero) try: # Si no es XBMC, siempre a "Silent" from platformcode import platformtools # antes # f=open(nombrefichero,"wb") try: import xbmc nombrefichero = xbmc.makeLegalFilename(nombrefichero) except: pass logger.info("filename=" + nombrefichero) # El fichero existe y se quiere continuar if filetools.exists(nombrefichero) and continuar: f = filetools.file_open(nombrefichero, 'r+b', vfs=VFS) if resumir: exist_size = filetools.getsize(nombrefichero) logger.info("the file exists, size=%d" % exist_size) grabado = exist_size f.seek(exist_size) else: exist_size = 0 grabado = 0 # el fichero ya existe y no se quiere continuar, se aborta elif filetools.exists(nombrefichero) and not continuar: logger.info("the file exists, it does not download again") return -3 # el fichero no existe else: exist_size = 0 logger.info("the file does not exist") f = filetools.file_open(nombrefichero, 'wb', vfs=VFS) grabado = 0 # Crea el diálogo de progreso if not silent: progreso = platformtools.dialog_progress("plugin", "Downloading...", url, nombrefichero) # Si la plataforma no devuelve un cuadro de diálogo válido, asume modo silencio if progreso is None: silent = True if "|" in url: additional_headers = url.split("|")[1] if "&" in additional_headers: additional_headers = additional_headers.split("&") else: additional_headers = [additional_headers] for additional_header in additional_headers: logger.info("additional_header: " + additional_header) name = re.findall("(.*?)=.*?", additional_header)[0] value = urllib.parse.unquote_plus( re.findall(".*?=(.*?)$", additional_header)[0]) headers.append([name, value]) url = url.split("|")[0] logger.info("url=" + url) # Timeout del socket a 60 segundos socket.setdefaulttimeout(60) h = urllib.request.HTTPHandler(debuglevel=0) request = urllib.request.Request(url) for header in headers: logger.info("Header=" + header[0] + ": " + header[1]) request.add_header(header[0], header[1]) if exist_size > 0: request.add_header('Range', 'bytes=%d-' % (exist_size, )) opener = urllib.request.build_opener(h) urllib.request.install_opener(opener) try: connexion = opener.open(request) except urllib.error.HTTPError as e: logger.error("error %d (%s) al abrir la url %s" % (e.code, e.msg, url)) f.close() if not silent: progreso.close() # El error 416 es que el rango pedido es mayor que el fichero => es que ya está completo if e.code == 416: return 0 else: return -2 try: totalfichero = int(connexion.headers["Content-Length"]) except ValueError: totalfichero = 1 if exist_size > 0: totalfichero = totalfichero + exist_size logger.info("Content-Length=%s" % totalfichero) blocksize = 100 * 1024 bloqueleido = connexion.read(blocksize) logger.info("Starting downloading the file, blocked=%s" % len(bloqueleido)) maxreintentos = 10 while len(bloqueleido) > 0: try: # Escribe el bloque leido f.write(bloqueleido) grabado += len(bloqueleido) percent = int(float(grabado) * 100 / float(totalfichero)) totalmb = float(float(totalfichero) / (1024 * 1024)) descargadosmb = float(float(grabado) / (1024 * 1024)) # Lee el siguiente bloque, reintentando para no parar todo al primer timeout reintentos = 0 while reintentos <= maxreintentos: try: before = time.time() bloqueleido = connexion.read(blocksize) after = time.time() if (after - before) > 0: velocidad = old_div(len(bloqueleido), (after - before)) falta = totalfichero - grabado if velocidad > 0: tiempofalta = old_div(falta, velocidad) else: tiempofalta = 0 # logger.info(sec_to_hms(tiempofalta)) if not silent: progreso.update( percent, "%.2fMB/%.2fMB (%d%%) %.2f Kb/s %s falta " % (descargadosmb, totalmb, percent, old_div(velocidad, 1024), sec_to_hms(tiempofalta))) break except: reintentos += 1 logger.info("ERROR in block download, retry %d" % reintentos) import traceback logger.error(traceback.print_exc()) # El usuario cancelo la descarga try: if progreso.iscanceled(): logger.info("Download of file canceled") f.close() progreso.close() return -1 except: pass # Ha habido un error en la descarga if reintentos > maxreintentos: logger.info("ERROR in the file download") f.close() if not silent: progreso.close() return -2 except: import traceback logger.error(traceback.print_exc()) f.close() if not silent: progreso.close() # platformtools.dialog_ok('Error al descargar' , 'Se ha producido un error' , 'al descargar el archivo') return -2 except: if url.startswith("rtmp"): error = downloadfileRTMP(url, nombrefichero, silent) if error and not silent: from platformcode import platformtools platformtools.dialog_ok("No puedes descargar ese vídeo", "Las descargas en RTMP aún no", "están soportadas") else: import traceback from pprint import pprint exc_type, exc_value, exc_tb = sys.exc_info() lines = traceback.format_exception(exc_type, exc_value, exc_tb) for line in lines: line_splits = line.split("\n") for line_split in line_splits: logger.error(line_split) try: f.close() except: pass if not silent: try: progreso.close() except: pass logger.info("End of file download")
def get_environment(): """ Returns the most common OS, Kodi and Alpha environment variables, necessary for fault diagnosis """ try: import base64 import ast environment = config.get_platform(full_version=True) environment['num_version'] = str(environment['num_version']) environment['python_version'] = str(platform.python_version()) environment['os_release'] = str(platform.release()) if xbmc.getCondVisibility("system.platform.Windows"): try: if platform._syscmd_ver()[2]: environment['os_release'] = str(platform._syscmd_ver()[2]) except: pass environment['prod_model'] = '' if xbmc.getCondVisibility("system.platform.Android"): environment['os_name'] = 'Android' try: for label_a in subprocess.check_output('getprop').split('\n'): if 'build.version.release' in label_a: environment['os_release'] = str( scrapertools.find_single_match( label_a, r':\s*\[(.*?)\]$')) if 'product.model' in label_a: environment['prod_model'] = str( scrapertools.find_single_match( label_a, r':\s*\[(.*?)\]$')) except: try: for label_a in filetools.read(os.environ['ANDROID_ROOT'] + '/build.prop').split(): if 'build.version.release' in label_a: environment['os_release'] = str( scrapertools.find_single_match( label_a, '=(.*?)$')) if 'product.model' in label_a: environment['prod_model'] = str( scrapertools.find_single_match( label_a, '=(.*?)$')) except: pass elif xbmc.getCondVisibility("system.platform.Linux.RaspberryPi"): environment['os_name'] = 'RaspberryPi' else: environment['os_name'] = str(platform.system()) environment['machine'] = str(platform.machine()) environment['architecture'] = str(sys.maxsize > 2**32 and "64-bit" or "32-bit") environment['language'] = str(xbmc.getInfoLabel('System.Language')) environment['cpu_usage'] = str(xbmc.getInfoLabel('System.CpuUsage')) environment['mem_total'] = str( xbmc.getInfoLabel('System.Memory(total)')).replace('MB', '').replace( 'KB', '') environment['mem_free'] = str( xbmc.getInfoLabel('System.Memory(free)')).replace('MB', '').replace( 'KB', '') if not environment['mem_total'] or not environment['mem_free']: try: if environment['os_name'].lower() == 'windows': kernel32 = ctypes.windll.kernel32 c_ulong = ctypes.c_ulong c_ulonglong = ctypes.c_ulonglong class MEMORYSTATUS(ctypes.Structure): _fields_ = [('dwLength', c_ulong), ('dwMemoryLoad', c_ulong), ('dwTotalPhys', c_ulonglong), ('dwAvailPhys', c_ulonglong), ('dwTotalPageFile', c_ulonglong), ('dwAvailPageFile', c_ulonglong), ('dwTotalVirtual', c_ulonglong), ('dwAvailVirtual', c_ulonglong), ('availExtendedVirtual', c_ulonglong)] memoryStatus = MEMORYSTATUS() memoryStatus.dwLength = ctypes.sizeof(MEMORYSTATUS) kernel32.GlobalMemoryStatus(ctypes.byref(memoryStatus)) environment['mem_total'] = str( old_div(int(memoryStatus.dwTotalPhys), (1024**2))) environment['mem_free'] = str( old_div(int(memoryStatus.dwAvailPhys), (1024**2))) else: with open('/proc/meminfo') as f: meminfo = f.read() environment['mem_total'] = str( old_div( int( re.search(r'MemTotal:\s+(\d+)', meminfo).groups()[0]), 1024)) environment['mem_free'] = str( old_div( int( re.search(r'MemAvailable:\s+(\d+)', meminfo).groups()[0]), 1024)) except: environment['mem_total'] = '' environment['mem_free'] = '' try: environment['kodi_buffer'] = '20' environment['kodi_bmode'] = '0' environment['kodi_rfactor'] = '4.0' if filetools.exists( filetools.join(xbmc.translatePath("special://userdata"), "advancedsettings.xml")): advancedsettings = filetools.read( filetools.join(xbmc.translatePath("special://userdata"), "advancedsettings.xml")).split('\n') for label_a in advancedsettings: if 'memorysize' in label_a: environment['kodi_buffer'] = str( old_div( int( scrapertools.find_single_match( label_a, r'>(\d+)<\/')), 1024**2)) if 'buffermode' in label_a: environment['kodi_bmode'] = str( scrapertools.find_single_match( label_a, r'>(\d+)<\/')) if 'readfactor' in label_a: environment['kodi_rfactor'] = str( scrapertools.find_single_match( label_a, r'>(.*?)<\/')) except: pass environment['userdata_path'] = str( xbmc.translatePath(config.get_data_path())) try: if environment['os_name'].lower() == 'windows': free_bytes = ctypes.c_ulonglong(0) ctypes.windll.kernel32.GetDiskFreeSpaceExW( ctypes.c_wchar_p(environment['userdata_path']), None, None, ctypes.pointer(free_bytes)) environment['userdata_free'] = str( round(float(free_bytes.value) / (1024**3), 3)) else: disk_space = os.statvfs(environment['userdata_path']) if not disk_space.f_frsize: disk_space.f_frsize = disk_space.f_frsize.f_bsize environment['userdata_free'] = str( round((float(disk_space.f_bavail) / (1024**3)) * float(disk_space.f_frsize), 3)) except: environment['userdata_free'] = '?' try: environment['videolab_series'] = '?' environment['videolab_episodios'] = '?' environment['videolab_pelis'] = '?' environment['videolab_path'] = str( xbmc.translatePath(config.get_videolibrary_path())) if filetools.exists( filetools.join(environment['videolab_path'], config.get_setting("folder_tvshows"))): environment['videolab_series'] = str( len( filetools.listdir( filetools.join( environment['videolab_path'], config.get_setting("folder_tvshows"))))) counter = 0 for root, folders, files in filetools.walk( filetools.join(environment['videolab_path'], config.get_setting("folder_tvshows"))): for file in files: if file.endswith('.strm'): counter += 1 environment['videolab_episodios'] = str(counter) if filetools.exists( filetools.join(environment['videolab_path'], config.get_setting("folder_movies"))): environment['videolab_pelis'] = str( len( filetools.listdir( filetools.join( environment['videolab_path'], config.get_setting("folder_movies"))))) except: pass try: video_updates = ['No', 'Inicio', 'Una vez', 'Inicio+Una vez'] environment['videolab_update'] = str( video_updates[config.get_setting("update", "videolibrary")]) except: environment['videolab_update'] = '?' try: if environment['os_name'].lower() == 'windows': free_bytes = ctypes.c_ulonglong(0) ctypes.windll.kernel32.GetDiskFreeSpaceExW( ctypes.c_wchar_p(environment['videolab_path']), None, None, ctypes.pointer(free_bytes)) environment['videolab_free'] = str( round(float(free_bytes.value) / (1024**3), 3)) else: disk_space = os.statvfs(environment['videolab_path']) if not disk_space.f_frsize: disk_space.f_frsize = disk_space.f_frsize.f_bsize environment['videolab_free'] = str( round((float(disk_space.f_bavail) / (1024**3)) * float(disk_space.f_frsize), 3)) except: environment['videolab_free'] = '?' # environment['torrent_list'] = [] # environment['torrentcli_option'] = '' # environment['torrent_error'] = '' # environment['torrentcli_rar'] = config.get_setting("mct_rar_unpack", server="torrent", default=True) # environment['torrentcli_backgr'] = config.get_setting("mct_background_download", server="torrent", default=True) # environment['torrentcli_lib_path'] = config.get_setting("libtorrent_path", server="torrent", default="") # if environment['torrentcli_lib_path']: # lib_path = 'Activo' # else: # lib_path = 'Inactivo' # environment['torrentcli_unrar'] = config.get_setting("unrar_path", server="torrent", default="") # if environment['torrentcli_unrar']: # if xbmc.getCondVisibility("system.platform.Android"): # unrar = 'Android' # else: # unrar, bin = filetools.split(environment['torrentcli_unrar']) # unrar = unrar.replace('\\', '/') # if not unrar.endswith('/'): # unrar = unrar + '/' # unrar = scrapertools.find_single_match(unrar, '\/([^\/]+)\/$').capitalize() # else: # unrar = 'Inactivo' # torrent_id = config.get_setting("torrent_client", server="torrent", default=0) # environment['torrentcli_option'] = str(torrent_id) # torrent_options = platformtools.torrent_client_installed() # if lib_path == 'Activo': # torrent_options = ['MCT'] + torrent_options # torrent_options = ['BT'] + torrent_options # environment['torrent_list'].append({'Torrent_opt': str(torrent_id), 'Libtorrent': lib_path, \ # 'RAR_Auto': str(environment['torrentcli_rar']), \ # 'RAR_backgr': str(environment['torrentcli_backgr']), \ # 'UnRAR': unrar}) # environment['torrent_error'] = config.get_setting("libtorrent_error", server="torrent", default="") # if environment['torrent_error']: # environment['torrent_list'].append({'Libtorrent_error': environment['torrent_error']}) # for torrent_option in torrent_options: # cliente = dict() # cliente['D_load_Path'] = '' # cliente['Libre'] = '?' # cliente['Plug_in'] = torrent_option.replace('Plugin externo: ', '') # if cliente['Plug_in'] == 'BT': # cliente['D_load_Path'] = str(config.get_setting("bt_download_path", server="torrent", default='')) # if not cliente['D_load_Path']: continue # cliente['Buffer'] = str(config.get_setting("bt_buffer", server="torrent", default=50)) # elif cliente['Plug_in'] == 'MCT': # cliente['D_load_Path'] = str(config.get_setting("mct_download_path", server="torrent", default='')) # if not cliente['D_load_Path']: continue # cliente['Buffer'] = str(config.get_setting("mct_buffer", server="torrent", default=50)) # elif xbmc.getCondVisibility('System.HasAddon("plugin.video.%s")' % cliente['Plug_in']): # __settings__ = xbmcaddon.Addon(id="plugin.video.%s" % cliente['Plug_in']) # cliente['Plug_in'] = cliente['Plug_in'].capitalize() # if cliente['Plug_in'] == 'Torrenter': # cliente['D_load_Path'] = str(xbmc.translatePath(__settings__.getSetting('storage'))) # if not cliente['D_load_Path']: # cliente['D_load_Path'] = str(filetools.join(xbmc.translatePath("special://home/"), \ # "cache", "xbmcup", "plugin.video.torrenter", # "Torrenter")) # cliente['Buffer'] = str(__settings__.getSetting('pre_buffer_bytes')) # else: # cliente['D_load_Path'] = str(xbmc.translatePath(__settings__.getSetting('download_path'))) # cliente['Buffer'] = str(__settings__.getSetting('buffer_size')) # if __settings__.getSetting('download_storage') == '1' and __settings__.getSetting('memory_size'): # cliente['Memoria'] = str(__settings__.getSetting('memory_size')) # if cliente['D_load_Path']: # try: # if environment['os_name'].lower() == 'windows': # free_bytes = ctypes.c_ulonglong(0) # ctypes.windll.kernel32.GetDiskFreeSpaceExW(ctypes.c_wchar_p(cliente['D_load_Path']), # None, None, ctypes.pointer(free_bytes)) # cliente['Libre'] = str(round(float(free_bytes.value) / \ # (1024 ** 3), 3)).replace('.', ',') # else: # disk_space = os.statvfs(cliente['D_load_Path']) # if not disk_space.f_frsize: disk_space.f_frsize = disk_space.f_frsize.f_bsize # cliente['Libre'] = str(round((float(disk_space.f_bavail) / \ # (1024 ** 3)) * float(disk_space.f_frsize), 3)).replace('.', ',') # except: # pass # environment['torrent_list'].append(cliente) environment['proxy_active'] = '' try: proxy_channel_bloqued_str = base64.b64decode( config.get_setting('proxy_channel_bloqued')).decode('utf-8') proxy_channel_bloqued = dict() proxy_channel_bloqued = ast.literal_eval(proxy_channel_bloqued_str) for channel_bloqued, proxy_active in list( proxy_channel_bloqued.items()): if proxy_active != 'OFF': environment['proxy_active'] += channel_bloqued + ', ' except: pass if not environment['proxy_active']: environment['proxy_active'] = 'OFF' environment['proxy_active'] = environment['proxy_active'].rstrip(', ') for root, folders, files in filetools.walk( xbmc.translatePath("special://logpath/")): for file in files: if file.lower() in ['kodi.log', 'jarvis.log', 'spmc.log', 'cemc.log', \ 'mygica.log', 'wonderbox.log', 'leiapp,log', \ 'leianmc.log', 'kodiapp.log', 'anmc.log', \ 'latin-anmc.log']: environment['log_path'] = str(filetools.join(root, file)) break else: environment['log_path'] = '' break if environment['log_path']: environment['log_size_bytes'] = str( filetools.getsize(environment['log_path'])) environment['log_size'] = str(round(float(environment['log_size_bytes']) / \ (1024 * 1024), 3)) else: environment['log_size_bytes'] = '' environment['log_size'] = '' environment['debug'] = str(config.get_setting('debug')) environment['addon_version'] = str(config.get_addon_version()) except: logger.error(traceback.format_exc()) environment = {} environment['log_size'] = '' environment['cpu_usage'] = '' environment['python_version'] = '' environment['log_path'] = '' environment['userdata_free'] = '' environment['mem_total'] = '' environment['machine'] = '' environment['platform'] = '' environment['videolab_path'] = '' environment['num_version'] = '' environment['os_name'] = '' environment['video_db'] = '' environment['userdata_path'] = '' environment['log_size_bytes'] = '' environment['name_version'] = '' environment['language'] = '' environment['mem_free'] = '' environment['prod_model'] = '' environment['proxy_active'] = '' environment['architecture'] = '' environment['os_release'] = '' environment['videolab_free'] = '' environment['kodi_buffer'] = '' environment['kodi_bmode'] = '' environment['kodi_rfactor'] = '' environment['videolab_series'] = '' environment['videolab_episodios'] = '' environment['videolab_pelis'] = '' environment['videolab_update'] = '' environment['debug'] = '' environment['addon_version'] = '' environment['torrent_list'] = [] environment['torrentcli_option'] = '' environment['torrentcli_rar'] = '' environment['torrentcli_lib_path'] = '' environment['torrentcli_unrar'] = '' environment['torrent_error'] = '' return environment
def conf_tools(item): logger.info() # Activar/Desactivar canales if item.extra == "channels_onoff": import channelselector from core import channeltools from platformcode import platformtools channel_list = channelselector.filterchannels("allchannelstatus") channel_language = config.get_setting("channel_language") if channel_language == "": channel_language = "all" excluded_channels = ['tengourl', 'buscador', 'libreria', 'configuracion', 'novedades', 'personal', 'ayuda'] list_controls = [] try: list_controls.append({'id': "all_channels", 'type': "list", 'label': "Todos los canales", 'default': 0, 'enabled': True, 'visible': True, 'lvalues': ['', 'Activar todos', 'Desactivar todos', 'Establecer estado por defecto']}) for channel in channel_list: # Si el canal esta en la lista de exclusiones lo saltamos if channel.channel not in excluded_channels: # Se cargan los ajustes del archivo json del canal jsonchannel = channeltools.get_channel_json(channel.channel) if jsonchannel.get("settings") or jsonchannel.get("active"): channel_parameters = channeltools.get_channel_parameters(channel.channel) # No incluir si es un canal para adultos, y el modo adulto está desactivado if (channel_parameters["adult"] == "true" and config.get_setting("adult_mode") == "false"): continue # No incluir si el canal es en un idioma filtrado if (channel_language != "all" and channel_parameters["language"] != channel_language): continue xml_status = None status = None xml_status = channel_parameters["active"] status_control = "" if config.get_setting("enabled", channel.channel): status = config.get_setting("enabled", channel.channel) # logger.info(channel.channel + " | Status: " + str(status)) else: status = xml_status # logger.info(channel.channel + " | Status (XML): " + str(status)) # Se establece el estado if status == "false" or status is False: status = False elif status == "true" or status is True: status = True if xml_status == "false": status_control = " [COLOR grey](Desactivado por defecto)[/COLOR]" if status is not None: control = {'id': channel.channel, 'type': "bool", 'label': channel_parameters["title"] + status_control, 'default': status, 'enabled': True, 'visible': True} list_controls.append(control) else: logger.info("Algo va mal con el canal " + channel.channel) else: continue return platformtools.show_channel_settings(list_controls=list_controls, caption="Activar/Desactivar canales", callback="channel_status") except: import traceback from platformcode import platformtools logger.info(channel.title + " | Detalle del error: %s" % traceback.format_exc()) platformtools.dialog_notification("Error", "Se ha producido un error con el canal" + channel.title) # Comprobacion de archivos channel_data.json elif item.extra == "lib_check_datajson": itemlist = [] import channelselector from core import channeltools channel_list = channelselector.filterchannels("allchannelstatus") # Tener una lista de exclusion no tiene mucho sentido por que se comprueba si # el xml tiene "settings", pero por si acaso se deja excluded_channels = ['tengourl', 'configuracion', 'personal', 'ayuda'] try: import os from core import jsontools for channel in channel_list: needsfix = None list_status = None list_controls = None default_settings = None channeljson_exists = None # Se convierte el "channel.channel" del canal biblioteca para que no de error if channel.channel == "libreria": channel.channel = "biblioteca" # Se comprueba si el canal esta en la lista de exclusiones if channel.channel not in excluded_channels: # Se comprueba que tenga "settings", sino se salta jsonchannel = channeltools.get_channel_json(channel.channel) if not jsonchannel.get("settings"): itemlist.append(Item(channel=CHANNELNAME, title=channel.title + " - No tiene ajustes por defecto", action="", folder=False, thumbnail=channel.thumbnail)) continue # logger.info(channel.channel + " SALTADO!") # Se cargan los ajustes del archivo json del canal file_settings = os.path.join(config.get_data_path(), "settings_channels", channel.channel + "_data.json") dict_settings = {} dict_file = {} if filetools.exists(file_settings): # logger.info(channel.channel + " Tiene archivo _data.json") channeljson_exists = "true" # Obtenemos configuracion guardada de ../settings/channel_data.json try: dict_file = jsontools.load_json(open(file_settings, "rb").read()) if isinstance(dict_file, dict) and 'settings' in dict_file: dict_settings = dict_file['settings'] except EnvironmentError: logger.info("ERROR al leer el archivo: {0}".format(file_settings)) else: # logger.info(channel.channel + " No tiene archivo _data.json") channeljson_exists = "false" if channeljson_exists == "true": try: datajson_size = filetools.getsize(file_settings) except: import traceback logger.info(channel.title + " | Detalle del error: %s" % traceback.format_exc()) else: datajson_size = None # Si el _data.json esta vacio o no existe... if (len(dict_settings) and datajson_size) == 0 or channeljson_exists == "false": # Obtenemos controles del archivo ../channels/channel.xml needsfix = "true" try: # Se cargan los ajustes por defecto list_controls, default_settings = channeltools.get_channel_controls_settings(channel.channel) # logger.info(channel.title + " | Default: %s" % default_settings) except: import traceback logger.info(channel.title + " | Detalle del error: %s" % traceback.format_exc()) # default_settings = {} # Si _data.json necesita ser reparado o no existe... if needsfix == "true" or channeljson_exists == "false": if default_settings is not None: # Creamos el channel_data.json default_settings.update(dict_settings) dict_settings = default_settings dict_file['settings'] = dict_settings # Creamos el archivo ../settings/channel_data.json json_data = jsontools.dump_json(dict_file) try: open(file_settings, "wb").write(json_data) # logger.info(channel.channel + " - Archivo _data.json GUARDADO!") # El channel_data.json se ha creado/modificado list_status = " - [COLOR red] CORREGIDO!![/COLOR]" except EnvironmentError: logger.info("ERROR al salvar el archivo: {0}".format(file_settings)) else: if default_settings is None: list_status = " - [COLOR red] Imposible cargar los ajustes por defecto![/COLOR]" else: # logger.info(channel.channel + " - NO necesita correccion!") needsfix = "false" # Si se ha establecido el estado del canal se añade a la lista if needsfix is not None: if needsfix == "true": if channeljson_exists == "false": list_status = " - [COLOR red] Ajustes creados!![/COLOR]" else: list_status = " - [COLOR green] No necesita correccion[/COLOR]" else: # Si "needsfix" es "false" y "datjson_size" es None habra # ocurrido algun error if datajson_size is None: list_status = " - [COLOR red] Ha ocurrido algun error[/COLOR]" else: list_status = " - [COLOR green] No necesita correccion[/COLOR]" if list_status is not None: itemlist.append(Item(channel=CHANNELNAME, title=channel.title + list_status, action="", folder=False, thumbnail=channel.thumbnail)) else: logger.info("Algo va mal con el canal " + channel.channel) # Si el canal esta en la lista de exclusiones lo saltamos else: continue except: import traceback from platformcode import platformtools logger.info(channel.title + " | Detalle del error: %s" % traceback.format_exc()) platformtools.dialog_notification("Error", "Se ha producido un error con el canal" + channel.title) return itemlist else: from platformcode import platformtools platformtools.dialog_notification("pelisalacarta", "Error!") platformtools.itemlist_update(Item(channel=CHANNELNAME, action="submenu_tools"))
def downloadfile(url, nombrefichero, headers=None, silent=False, continuar=False, resumir=True, header=''): logger.info("url= " + url) logger.info("filename= " + nombrefichero) if headers is None: headers = [] if not header: header = "plugin" progreso = None if config.is_xbmc() and nombrefichero.startswith("special://"): import xbmc nombrefichero = xbmc.translatePath(nombrefichero) try: # If it is not XBMC, always "Silent" from platformcode import platformtools # before # f=open(nombrefichero,"wb") try: import xbmc nombrefichero = xbmc.makeLegalFilename(nombrefichero) except: pass logger.info("filename= " + nombrefichero) # The file exists and you want to continue if filetools.exists(nombrefichero) and continuar: f = filetools.file_open(nombrefichero, 'r+b', vfs=VFS) if resumir: exist_size = filetools.getsize(nombrefichero) logger.info("the file exists, size= %d" % exist_size) grabado = exist_size f.seek(exist_size) else: exist_size = 0 grabado = 0 # the file already exists and you don't want to continue, it aborts elif filetools.exists(nombrefichero) and not continuar: logger.info("the file exists, it does not download again") return -3 # the file does not exist else: exist_size = 0 logger.info("the file does not exist") f = filetools.file_open(nombrefichero, 'wb', vfs=VFS) grabado = 0 # Create the progress dialog if not silent: progreso = platformtools.dialog_progress(header, "Downloading..." + '\n' + url + '\n' + nombrefichero) # If the platform does not return a valid dialog box, it assumes silent mode if progreso is None: silent = True if "|" in url: additional_headers = url.split("|")[1] if "&" in additional_headers: additional_headers = additional_headers.split("&") else: additional_headers = [additional_headers] for additional_header in additional_headers: logger.info("additional_header: " + additional_header) name = re.findall("(.*?)=.*?", additional_header)[0] value = urllib.parse.unquote_plus(re.findall(".*?=(.*?)$", additional_header)[0]) headers.append([name, value]) url = url.split("|")[0] logger.info("url=" + url) # Socket timeout at 60 seconds socket.setdefaulttimeout(60) h = urllib.request.HTTPHandler(debuglevel=0) request = urllib.request.Request(url) for header in headers: logger.info("Header= " + header[0] + ": " + header[1]) request.add_header(header[0], header[1]) if exist_size > 0: request.add_header('Range', 'bytes= %d-' % (exist_size,)) opener = urllib.request.build_opener(h) urllib.request.install_opener(opener) try: connexion = opener.open(request) except urllib.error.HTTPError as e: logger.error("error %d (%s) opening url %s" % (e.code, e.msg, url)) f.close() if not silent: progreso.close() # Error 416 is that the requested range is greater than the file => is that it is already complete if e.code == 416: return 0 else: return -2 try: totalfichero = int(connexion.headers["Content-Length"]) except ValueError: totalfichero = 1 if exist_size > 0: totalfichero = totalfichero + exist_size logger.info("Content-Length= %s" % totalfichero) blocksize = 100 * 1024 bloqueleido = connexion.read(blocksize) logger.info("Starting downloading the file, blocked= %s" % len(bloqueleido)) maxreintentos = 10 while len(bloqueleido) > 0: try: # Write the block read f.write(bloqueleido) grabado += len(bloqueleido) percent = int(float(grabado) * 100 / float(totalfichero)) totalmb = float(float(totalfichero) / (1024 * 1024)) descargadosmb = float(float(grabado) / (1024 * 1024)) # Read the next block, retrying not to stop everything at the first timeout reintentos = 0 while reintentos <= maxreintentos: try: before = time.time() bloqueleido = connexion.read(blocksize) after = time.time() if (after - before) > 0: velocidad = old_div(len(bloqueleido), (after - before)) falta = totalfichero - grabado if velocidad > 0: tiempofalta = old_div(falta, velocidad) else: tiempofalta = 0 # logger.info(sec_to_hms(tiempofalta)) if not silent: progreso.update(percent, "%.2fMB/%.2fMB (%d%%) %.2f Kb/s %s" % (descargadosmb, totalmb, percent, old_div(velocidad, 1024), sec_to_hms(tiempofalta))) break except: reintentos += 1 logger.info("ERROR in block download, retry %d" % reintentos) import traceback logger.error(traceback.print_exc()) # The user cancels the download try: if progreso.iscanceled(): logger.info("Download of file canceled") f.close() progreso.close() return -1 except: pass # There was an error in the download if reintentos > maxreintentos: logger.info("ERROR in the file download") f.close() if not silent: progreso.close() return -2 except: import traceback logger.error(traceback.print_exc()) f.close() if not silent: progreso.close() # platformtools.dialog_ok('Error al descargar' , 'Se ha producido un error' , 'al descargar el archivo') return -2 except: if url.startswith("rtmp"): error = downloadfileRTMP(url, nombrefichero, silent) if error and not silent: from platformcode import platformtools platformtools.dialog_ok("You cannot download that video "," RTMP downloads not yet supported") else: import traceback from pprint import pprint exc_type, exc_value, exc_tb = sys.exc_info() lines = traceback.format_exception(exc_type, exc_value, exc_tb) for line in lines: line_splits = line.split("\n") for line_split in line_splits: logger.error(line_split) try: f.close() except: pass if not silent: try: progreso.close() except: pass logger.info("End of file download")
def get_environment(): """ Devuelve las variables de entorno del OS, de Kodi y de Alfa más habituales, necesarias para el diagnóstico de fallos """ try: import base64 import ast environment = config.get_platform(full_version=True) environment['num_version'] = str(environment['num_version']) environment['python_version'] = str(platform.python_version()) environment['os_release'] = str(platform.release()) if xbmc.getCondVisibility("system.platform.Windows"): try: if platform._syscmd_ver()[2]: environment['os_release'] = str(platform._syscmd_ver()[2]) except: pass environment['prod_model'] = '' if xbmc.getCondVisibility("system.platform.Android"): environment['os_name'] = 'Android' try: for label_a in subprocess.check_output('getprop').split('\n'): if 'build.version.release' in label_a: environment['os_release'] = str( scrapertools.find_single_match( label_a, ':\s*\[(.*?)\]$')) if 'product.model' in label_a: environment['prod_model'] = str( scrapertools.find_single_match( label_a, ':\s*\[(.*?)\]$')) except: try: for label_a in filetools.read(os.environ['ANDROID_ROOT'] + '/build.prop').split(): if 'build.version.release' in label_a: environment['os_release'] = str( scrapertools.find_single_match( label_a, '=(.*?)$')) if 'product.model' in label_a: environment['prod_model'] = str( scrapertools.find_single_match( label_a, '=(.*?)$')) except: pass elif xbmc.getCondVisibility("system.platform.Linux.RaspberryPi"): environment['os_name'] = 'RaspberryPi' else: environment['os_name'] = str(platform.system()) environment['machine'] = str(platform.machine()) environment['architecture'] = str(sys.maxsize > 2**32 and "64-bit" or "32-bit") environment['language'] = str(xbmc.getInfoLabel('System.Language')) environment['cpu_usage'] = str(xbmc.getInfoLabel('System.CpuUsage')) environment['mem_total'] = str( xbmc.getInfoLabel('System.Memory(total)')).replace('MB', '').replace( 'KB', '') environment['mem_free'] = str( xbmc.getInfoLabel('System.Memory(free)')).replace('MB', '').replace( 'KB', '') if not environment['mem_total'] or not environment['mem_free']: try: if environment['os_name'].lower() == 'windows': kernel32 = ctypes.windll.kernel32 c_ulong = ctypes.c_ulong c_ulonglong = ctypes.c_ulonglong class MEMORYSTATUS(ctypes.Structure): _fields_ = [('dwLength', c_ulong), ('dwMemoryLoad', c_ulong), ('dwTotalPhys', c_ulonglong), ('dwAvailPhys', c_ulonglong), ('dwTotalPageFile', c_ulonglong), ('dwAvailPageFile', c_ulonglong), ('dwTotalVirtual', c_ulonglong), ('dwAvailVirtual', c_ulonglong), ('availExtendedVirtual', c_ulonglong)] memoryStatus = MEMORYSTATUS() memoryStatus.dwLength = ctypes.sizeof(MEMORYSTATUS) kernel32.GlobalMemoryStatus(ctypes.byref(memoryStatus)) environment['mem_total'] = str( int(memoryStatus.dwTotalPhys) / (1024**2)) environment['mem_free'] = str( int(memoryStatus.dwAvailPhys) / (1024**2)) else: with open('/proc/meminfo') as f: meminfo = f.read() environment['mem_total'] = str( int( re.search(r'MemTotal:\s+(\d+)', meminfo).groups()[0]) / 1024) environment['mem_free'] = str( int( re.search(r'MemAvailable:\s+(\d+)', meminfo).groups()[0]) / 1024) except: environment['mem_total'] = '' environment['mem_free'] = '' try: environment['kodi_buffer'] = '20' environment['kodi_bmode'] = '0' environment['kodi_rfactor'] = '4.0' if filetools.exists( filetools.join(xbmc.translatePath("special://userdata"), "advancedsettings.xml")): advancedsettings = filetools.read( filetools.join(xbmc.translatePath("special://userdata"), "advancedsettings.xml")).split('\n') for label_a in advancedsettings: if 'memorysize' in label_a: environment['kodi_buffer'] = str( int( scrapertools.find_single_match( label_a, '>(\d+)<\/')) / 1024**2) if 'buffermode' in label_a: environment['kodi_bmode'] = str( scrapertools.find_single_match( label_a, '>(\d+)<\/')) if 'readfactor' in label_a: environment['kodi_rfactor'] = str( scrapertools.find_single_match( label_a, '>(.*?)<\/')) except: pass environment['userdata_path'] = str( xbmc.translatePath(config.get_data_path())) try: if environment['os_name'].lower() == 'windows': free_bytes = ctypes.c_ulonglong(0) ctypes.windll.kernel32.GetDiskFreeSpaceExW( ctypes.c_wchar_p(environment['userdata_path']), None, None, ctypes.pointer(free_bytes)) environment['userdata_free'] = str( round(float(free_bytes.value) / (1024**3), 3)) else: disk_space = os.statvfs(environment['userdata_path']) if not disk_space.f_frsize: disk_space.f_frsize = disk_space.f_frsize.f_bsize environment['userdata_free'] = str(round((float(disk_space.f_bavail) / \ (1024**3)) * float(disk_space.f_frsize), 3)) except: environment['userdata_free'] = '?' try: environment['videolab_series'] = '?' environment['videolab_episodios'] = '?' environment['videolab_pelis'] = '?' environment['videolab_path'] = str( xbmc.translatePath(config.get_videolibrary_path())) if filetools.exists(filetools.join(environment['videolab_path'], \ config.get_setting("folder_tvshows"))): environment['videolab_series'] = str(len(filetools.listdir(filetools.join(environment['videolab_path'], \ config.get_setting("folder_tvshows"))))) counter = 0 for root, folders, files in filetools.walk(filetools.join(environment['videolab_path'], \ config.get_setting("folder_tvshows"))): for file in files: if file.endswith('.strm'): counter += 1 environment['videolab_episodios'] = str(counter) if filetools.exists(filetools.join(environment['videolab_path'], \ config.get_setting("folder_movies"))): environment['videolab_pelis'] = str(len(filetools.listdir(filetools.join(environment['videolab_path'], \ config.get_setting("folder_movies"))))) except: pass try: video_updates = ['No', 'Inicio', 'Una vez', 'Inicio+Una vez'] environment['videolab_update'] = str( video_updates[config.get_setting("update", "videolibrary")]) except: environment['videolab_update'] = '?' try: if environment['os_name'].lower() == 'windows': free_bytes = ctypes.c_ulonglong(0) ctypes.windll.kernel32.GetDiskFreeSpaceExW( ctypes.c_wchar_p(environment['videolab_path']), None, None, ctypes.pointer(free_bytes)) environment['videolab_free'] = str( round(float(free_bytes.value) / (1024**3), 3)) else: disk_space = os.statvfs(environment['videolab_path']) if not disk_space.f_frsize: disk_space.f_frsize = disk_space.f_frsize.f_bsize environment['videolab_free'] = str(round((float(disk_space.f_bavail) / \ (1024**3)) * float(disk_space.f_frsize), 3)) except: environment['videolab_free'] = '?' environment['torrentcli_option'] = '' environment['torrentcli_name'] = '' environment['torrentcli_dload_path'] = '' environment['torrentcli_buffer'] = '' environment['torrentcli_dload_estrgy'] = '' environment['torrentcli_mem_size'] = '' environment['torrentcli_free'] = '' torrent_id = config.get_setting("torrent_client", server="torrent", default=0) environment['torrentcli_option'] = str(torrent_id) if torrent_id > 0: torrent_id = torrent_id - 3 if torrent_id < 0: logger.error('torrent_id: ' + str(torrent_id) + ' / torrent_options: ' + str(platformtools.torrent_client_installed())) torrent_options = platformtools.torrent_client_installed() if torrent_options and torrent_id >= 0: environment['torrentcli_name'] = torrent_options[ torrent_id].replace('Plugin externo: ', '') if xbmc.getCondVisibility('System.HasAddon("plugin.video.%s")' % environment['torrentcli_name']): __settings__ = xbmcaddon.Addon(id="plugin.video.%s" % environment['torrentcli_name']) environment['torrentcli_name'] = environment[ 'torrentcli_name'].capitalize() if environment['torrentcli_name'] == 'Torrenter': environment['torrentcli_dload_path'] = str( xbmc.translatePath(__settings__.getSetting('storage'))) environment['torrentcli_buffer'] = str( __settings__.getSetting('pre_buffer_bytes')) else: environment['torrentcli_dload_path'] = str( xbmc.translatePath( __settings__.getSetting('download_path'))) environment['torrentcli_buffer'] = str( __settings__.getSetting('buffer_size')) environment['torrentcli_dload_estrgy'] = str( __settings__.getSetting('download_storage')) environment['torrentcli_mem_size'] = str( __settings__.getSetting('memory_size')) if environment['torrentcli_dload_path']: try: if environment['os_name'].lower() == 'windows': free_bytes = ctypes.c_ulonglong(0) ctypes.windll.kernel32.GetDiskFreeSpaceExW( ctypes.c_wchar_p(environment['torrentcli_dload_path']), None, None, ctypes.pointer(free_bytes)) environment['torrentcli_free'] = str(round(float(free_bytes.value) / \ (1024**3), 3)) else: disk_space = os.statvfs( environment['torrentcli_dload_path']) if not disk_space.f_frsize: disk_space.f_frsize = disk_space.f_frsize.f_bsize environment['torrentcli_free'] = str(round((float(disk_space.f_bavail) / \ (1024**3)) * float(disk_space.f_frsize), 3)) except: environment['torrentcli_free'] = '?' environment['proxy_active'] = '' try: proxy_channel_bloqued_str = base64.b64decode( config.get_setting('proxy_channel_bloqued')).decode('utf-8') proxy_channel_bloqued = dict() proxy_channel_bloqued = ast.literal_eval(proxy_channel_bloqued_str) for channel_bloqued, proxy_active in proxy_channel_bloqued.items(): if proxy_active == 'ON': environment['proxy_active'] += channel_bloqued + ', ' except: pass if not environment['proxy_active']: environment['proxy_active'] = 'OFF' environment['proxy_active'] = environment['proxy_active'].rstrip(', ') for root, folders, files in filetools.walk( xbmc.translatePath("special://logpath/")): for file in files: if file.lower() in ['kodi.log', 'jarvis.log', 'spmc.log', 'cemc.log', \ 'mygica.log', 'wonderbox.log', 'leiapp,log', \ 'leianmc.log', 'kodiapp.log', 'anmc.log', \ 'latin-anmc.log']: environment['log_path'] = str(filetools.join(root, file)) break else: environment['log_path'] = '' break if environment['log_path']: environment['log_size_bytes'] = str( filetools.getsize(environment['log_path'])) environment['log_size'] = str(round(float(environment['log_size_bytes']) / \ (1024*1024), 3)) else: environment['log_size_bytes'] = '' environment['log_size'] = '' environment['debug'] = str(config.get_setting('debug')) environment['addon_version'] = str(config.get_addon_version()) except: logger.error(traceback.format_exc()) environment = {} environment['log_size'] = '' environment['cpu_usage'] = '' environment['python_version'] = '' environment['log_path'] = '' environment['userdata_free'] = '' environment['mem_total'] = '' environment['torrentcli_mem_size'] = '' environment['torrentcli_dload_path'] = '' environment['torrentcli_dload_estrgy'] = '' environment['machine'] = '' environment['platform'] = '' environment['torrentcli_buffer'] = '' environment['videolab_path'] = '' environment['num_version'] = '' environment['os_name'] = '' environment['torrentcli_free'] = '' environment['video_db'] = '' environment['userdata_path'] = '' environment['log_size_bytes'] = '' environment['name_version'] = '' environment['language'] = '' environment['mem_free'] = '' environment['prod_model'] = '' environment['proxy_active'] = '' environment['architecture'] = '' environment['os_release'] = '' environment['videolab_free'] = '' environment['torrentcli_name'] = '' environment['kodi_buffer'] = '' environment['kodi_bmode'] = '' environment['kodi_rfactor'] = '' environment['videolab_series'] = '' environment['videolab_episodios'] = '' environment['videolab_pelis'] = '' environment['videolab_update'] = '' environment['debug'] = '' environment['addon_version'] = '' environment['torrentcli_option'] = '' return environment
def conf_tools(item): logger.info() # Activar o desactivar canales if item.extra == "channels_onoff": import channelselector from core import channeltools channel_list = channelselector.filterchannels("allchannelstatus") channel_language = config.get_setting("channel_language") if channel_language == "": channel_language = "all" excluded_channels = ['tengourl', 'buscador', 'libreria', 'configuracion', 'novedades', 'personal', 'ayuda', 'descargas'] list_controls = [] try: list_controls.append({'id': "all_channels", 'type': "list", 'label': "Todos los canales", 'default': 0, 'enabled': True, 'visible': True, 'lvalues': ['', 'Activar todos', 'Desactivar todos', 'Establecer estado por defecto']}) for channel in channel_list: # Si el canal esta en la lista de exclusiones lo saltamos if channel.channel not in excluded_channels: # Se cargan los ajustes del archivo json del canal jsonchannel = channeltools.get_channel_json(channel.channel) if jsonchannel.get("settings") or jsonchannel.get("active"): channel_parameters = channeltools.get_channel_parameters(channel.channel) # No incluir si es un canal para adultos, y el modo adulto está desactivado if (channel_parameters["adult"] == "true" and config.get_setting("adult_mode") == "0"): continue # No incluir si el canal es en un idioma filtrado if (channel_language != "all" and channel_parameters["language"] != channel_language): continue status = None xml_status = channel_parameters["active"].replace("t", "T").replace("f", "F") xml_status = eval(xml_status) if config.get_setting("enabled", channel.channel): status = config.get_setting("enabled", channel.channel) status = status.replace("t", "T").replace("f", "F") status = eval(status) # logger.info(channel.channel + " | Status: " + str(status)) else: status = xml_status # logger.info(channel.channel + " | Status (XML): " + str(status)) status_control = "" if not xml_status: status_control = " [COLOR grey](Desactivado por defecto)[/COLOR]" if status is not None: control = {'id': channel.channel, 'type': "bool", 'label': channel_parameters["title"] + status_control, 'default': status, 'enabled': True, 'visible': True} list_controls.append(control) else: logger.info("Algo va mal con el canal " + channel.channel) else: continue return platformtools.show_channel_settings(list_controls=list_controls, caption="Canales", callback="channel_status", custom_button={"visible": False}) except: import traceback logger.info(channel.title + " | Detalle del error: %s" % traceback.format_exc()) platformtools.dialog_notification("Error", "Se ha producido un error con el canal %s" % channel.title) # Comprobacion de archivos channel_data.json elif item.extra == "lib_check_datajson": itemlist = [] import channelselector from core import channeltools channel_list = channelselector.filterchannels("allchannelstatus") # Tener una lista de exclusion no tiene mucho sentido por que se comprueba si # el xml tiene "settings", pero por si acaso se deja excluded_channels = ['tengourl', 'configuracion', 'personal', 'ayuda'] try: import os from core import jsontools for channel in channel_list: needsfix = None list_status = None list_controls = None default_settings = None channeljson_exists = None # Se convierte el "channel.channel" del canal biblioteca para que no de error if channel.channel == "libreria": channel.channel = "biblioteca" # Se comprueba si el canal esta en la lista de exclusiones if channel.channel not in excluded_channels: # Se comprueba que tenga "settings", sino se salta jsonchannel = channeltools.get_channel_json(channel.channel) if not jsonchannel.get("settings"): itemlist.append(Item(channel=CHANNELNAME, title=channel.title + " - No tiene ajustes por defecto", action="", folder=False, thumbnail=channel.thumbnail)) continue # logger.info(channel.channel + " SALTADO!") # Se cargan los ajustes del archivo json del canal file_settings = os.path.join(config.get_data_path(), "settings_channels", channel.channel + "_data.json") dict_settings = {} dict_file = {} if filetools.exists(file_settings): # logger.info(channel.channel + " Tiene archivo _data.json") channeljson_exists = "true" # Obtenemos configuracion guardada de ../settings/channel_data.json try: dict_file = jsontools.load_json(open(file_settings, "rb").read()) if isinstance(dict_file, dict) and 'settings' in dict_file: dict_settings = dict_file['settings'] except EnvironmentError: logger.info("ERROR al leer el archivo: %s" % file_settings) else: # logger.info(channel.channel + " No tiene archivo _data.json") channeljson_exists = "false" if channeljson_exists == "true": try: datajson_size = filetools.getsize(file_settings) except: import traceback logger.info(channel.title + " | Detalle del error: %s" % traceback.format_exc()) else: datajson_size = None # Si el _data.json esta vacio o no existe... if (len(dict_settings) and datajson_size) == 0 or channeljson_exists == "false": # Obtenemos controles del archivo ../channels/channel.xml needsfix = "true" try: # Se cargan los ajustes por defecto list_controls, default_settings = channeltools.get_channel_controls_settings(channel.channel) # logger.info(channel.title + " | Default: %s" % default_settings) except: import traceback logger.info(channel.title + " | Detalle del error: %s" % traceback.format_exc()) # default_settings = {} # Si _data.json necesita ser reparado o no existe... if needsfix == "true" or channeljson_exists == "false": if default_settings is not None: # Creamos el channel_data.json default_settings.update(dict_settings) dict_settings = default_settings dict_file['settings'] = dict_settings # Creamos el archivo ../settings/channel_data.json json_data = jsontools.dump_json(dict_file) try: open(file_settings, "wb").write(json_data) # logger.info(channel.channel + " - Archivo _data.json GUARDADO!") # El channel_data.json se ha creado/modificado list_status = " - [COLOR red] CORREGIDO!![/COLOR]" except EnvironmentError: logger.info("ERROR al salvar el archivo: %s" % file_settings) else: if default_settings is None: list_status = " - [COLOR red] Imposible cargar los ajustes por defecto![/COLOR]" else: # logger.info(channel.channel + " - NO necesita correccion!") needsfix = "false" # Si se ha establecido el estado del canal se añade a la lista if needsfix is not None: if needsfix == "true": if channeljson_exists == "false": list_status = " - Ajustes creados" list_colour = "red" else: list_status = " - No necesita correccion" list_colour = "green" else: # Si "needsfix" es "false" y "datjson_size" es None habra # ocurrido algun error if datajson_size is None: list_status = " - Ha ocurrido algun error" list_colour = "red" else: list_status = " - No necesita correccion" list_colour = "green" if list_status is not None: itemlist.append(Item(channel=CHANNELNAME, title=channel.title + list_status, action="", folder=False, thumbnail=channel.thumbnail, text_color=list_colour)) else: logger.info("Algo va mal con el canal %s" % channel.channel) # Si el canal esta en la lista de exclusiones lo saltamos else: continue except: import traceback logger.info(channel.title + " | Detalle del error: %s" % traceback.format_exc()) platformtools.dialog_notification("Error", "Se ha producido un error con el canal %s" % channel.title) return itemlist else: platformtools.dialog_notification("pelisalacarta", "Error!") platformtools.itemlist_update(Item(channel=CHANNELNAME, action="submenu_tools"))
def verify_directories_created(): """ Test if all the required directories are created """ from platformcode import logger from core import filetools from platformcode import xbmc_videolibrary logger.info() time.sleep(1) 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 = 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) try: # from core import scrapertools # Buscamos el archivo addon.xml del skin activo skindir = filetools.join("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 .*?>)') res = re.compile('(<res .*?>)', re.DOTALL).findall(data) for r in res: if 'default="true"' in r: # folder = scrapertools.find_single_match(r, 'folder="([^"]+)"') folder = re.search('folder="([^"]+)"', r).group(1) 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 verify_directories_created(): from platformcode import logger from core import filetools from platformcode import 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) # video store 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", "Film"], ["folder_tvshows", "Serie TV"]] 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)) # if the directory is created filetools.mkdir(content_path) from platformcode import xbmc_videolibrary xbmc_videolibrary.update_sources(get_setting("videolibrarypath")) xbmc_videolibrary.update_sources(get_setting("downloadpath")) try: from core import scrapertools # We look for the addon.xml file of the active skin skindir = filetools.join(xbmc.translatePath("special://home"), 'addons', xbmc.getSkinDir(), 'addon.xml') if not os.path.isdir(skindir): return # No need to show error in log if folder doesn't exist # We extract the name of the default resolution folder 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 # We check if it exists in the addon and if not, we create it 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)) # We copy the file to said folder from the 720p folder if it does not exist or if the size is different 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("When checking or creating the resolution folder") logger.error(traceback.format_exc())
def downloadbest(video_urls, title, continuar=False): logger.info() # Le da la vuelta, para poner el de más calidad primero ( list() es para que haga una copia ) invertida = list(video_urls) invertida.reverse() for elemento in invertida: # videotitle = elemento[0] url = elemento[1] if not PY3: logger.info("Downloading option " + title + " " + url.encode('ascii', 'ignore')) else: logger.info("Downloading option " + title + " " + url.encode('ascii', 'ignore').decode('utf-8')) # Calcula el fichero donde debe grabar try: fullpath = getfilefromtitle(url, title.strip()) # Si falla, es porque la URL no vale para nada except: import traceback logger.error(traceback.format_exc()) continue # Descarga try: ret = downloadfile(url, fullpath, continuar=continuar) # Llegados a este punto, normalmente es un timeout except urllib.error.URLError as e: import traceback logger.error(traceback.format_exc()) ret = -2 # El usuario ha cancelado la descarga if ret == -1: return -1 else: # El fichero ni siquiera existe if not filetools.exists(fullpath): logger.info( "-> You have not downloaded anything, testing with the following option if there is" ) # El fichero existe else: tamanyo = filetools.getsize(fullpath) # Tiene tamaño 0 if tamanyo == 0: logger.info( "-> Download a file with size 0, testing with the following option if it exists" ) os.remove(fullpath) else: logger.info( "-> Download a file with size %d, he takes it for good" % tamanyo) return 0 return -2
def verify_directories_created(): from core import logger from core import filetools from platformcode import 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"]] flag_call = True 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 if filetools.mkdir(content_path): if flag_call: # le pasamos el valor para que sepamos que se ha pasado por creación de directorio xbmc_videolibrary.ask_set_content(1) flag_call = False try: from core import scrapertools # Buscamos el archivo addon.xml del skin activo skindir = filetools.join(xbmc.translatePath("special://home"), 'addons', xbmc.getSkinDir(), 'addon.xml') # 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 verify_directories_created(): from platformcode import logger from core import filetools from platformcode import xbmc_library config_paths = [["librarypath", "library"], ["downloadpath", "downloads"], ["downloadlistpath", "downloads/list"], ["settings_path", "settings_channels"]] for path, default in config_paths: saved_path = get_setting(path) # Biblioteca if path == "librarypath": set_setting("library_version", "v4") if not saved_path: saved_path = xbmc_library.search_library_path() if saved_path: set_setting(path, saved_path) if not saved_path: saved_path = "storage/sod" + default set_setting(path, saved_path) if get_setting("library_set_content") == True and path in [ "librarypath", "downloadpath" ]: # logger.debug("library_set_content %s" % get_setting("library_set_content")) xbmc_library.add_sources(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_library_path(), saved_path) if not filetools.exists(content_path): logger.debug("Creating %s: %s" % (path, content_path)) if filetools.mkdir(content_path) and get_setting( "library_set_content") == True: xbmc_library.set_content(default) elif get_setting("library_ask_set_content") == 2: xbmc_library.set_content(default) try: from core import scrapertools # Buscamos el archivo addon.xml del skin activo skindir = filetools.join(xbmc.translatePath("special://home"), 'addons', xbmc.getSkinDir(), 'addon.xml') # 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 pelisalacarta 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())