276 lines
10 KiB
Python
276 lines
10 KiB
Python
from systems_definitions import get_system_name, filter_translatable_systems
|
|
from media_definitions import media_table, get_media_name
|
|
from config import SOURCE_FOLDER, DEST_FOLDER, GET_VIDEOS, SYSTEMS, CREATE_SYM_LINKS
|
|
import os
|
|
import shutil
|
|
|
|
|
|
def list_directories(path):
|
|
"""
|
|
Devuelve una lista de directorios en la ruta especificada.
|
|
Si SYSTEMS no está vacío, filtra por directorios que estén en SYSTEMS.
|
|
"""
|
|
if not SYSTEMS: # Si SYSTEMS está vacío, devolver todos los directorios
|
|
directories = [
|
|
name for name in os.listdir(path)
|
|
if os.path.isdir(os.path.join(path, name))
|
|
]
|
|
else:
|
|
directories = [
|
|
name for name in os.listdir(path)
|
|
if os.path.isdir(os.path.join(path, name)) and name in SYSTEMS
|
|
]
|
|
return directories
|
|
|
|
|
|
def list_files(path):
|
|
"""Devuelve una lista de ficheros (no directorios) en la ruta especificada, excluyendo archivos *.xml."""
|
|
files = [
|
|
name for name in os.listdir(path)
|
|
if os.path.isfile(os.path.join(path, name)) and not name.endswith(".xml")
|
|
]
|
|
return files
|
|
|
|
|
|
def directory_exists(path):
|
|
"""Comprueba si un directorio existe."""
|
|
return os.path.isdir(path)
|
|
|
|
|
|
def get_file_name_without_extension(file_path):
|
|
"""Devuelve el nombre del fichero sin su extensión."""
|
|
file_name, _ = os.path.splitext(os.path.basename(file_path))
|
|
return file_name
|
|
|
|
|
|
def find_file_extension(folder, base_name):
|
|
"""Busca un archivo que coincida con el nombre base y el sufijo, y devuelve solo la extensión."""
|
|
for file in os.listdir(folder):
|
|
if file.startswith(base_name):
|
|
_, extension = os.path.splitext(file) # Obtiene la extensión del archivo
|
|
return extension # Devuelve solo la extensión
|
|
return None
|
|
|
|
|
|
def create_file_list():
|
|
"""
|
|
Crea una lista de archivos basándose en los sistemas translatables
|
|
y las carpetas de origen y destino especificadas.
|
|
|
|
Procesa cada sistema en la lista filtrada:
|
|
- Verifica la existencia de la carpeta "downloaded_images".
|
|
- Agrega los archivos (ROMs) de cada sistema, excluyendo los archivos .xml.
|
|
- Gestiona las ROMs y crea un diccionario de medios asociado a cada archivo.
|
|
- Agrega el archivo "gamelist.xml" si está presente en el sistema.
|
|
|
|
Retorna:
|
|
list: Una lista de diccionarios, donde cada diccionario representa
|
|
un archivo ROM o un gamelist, incluyendo información de origen y destino.
|
|
|
|
Nota:
|
|
Usa funciones auxiliares como `filter_translatable_systems`,
|
|
`list_directories`, `directory_exists`, `list_files`,
|
|
`get_file_name_without_extension`, `find_file_extension` y otras.
|
|
|
|
Ejemplo de entrada:
|
|
- SOURCE_FOLDER: Carpeta donde se encuentran los sistemas originales.
|
|
- DEST_FOLDER: Carpeta donde se copiarán las ROMs y medios.
|
|
- media_table: Diccionario con las configuraciones de medios.
|
|
|
|
Ejemplo de salida:
|
|
[
|
|
{
|
|
"name": "rom_name",
|
|
"rom_source": "ruta/origen/rom",
|
|
"rom_dest": "ruta/destino/rom",
|
|
"media": {
|
|
"key_source": "ruta/origen/medio",
|
|
"key_dest": "ruta/destino/medio"
|
|
}
|
|
},
|
|
{
|
|
"name": "gamelist",
|
|
"rom_source": "ruta/origen/gamelist.xml",
|
|
"rom_dest": "ruta/destino/gamelist.xml"
|
|
}
|
|
]
|
|
"""
|
|
system_list = filter_translatable_systems(list_directories(SOURCE_FOLDER))
|
|
file_list = []
|
|
|
|
for system in system_list:
|
|
folder = os.path.join(SOURCE_FOLDER, system)
|
|
|
|
# Saltar sistemas sin la carpeta "downloaded_images"
|
|
if not directory_exists(os.path.join(folder, "downloaded_images")):
|
|
continue
|
|
|
|
# Añade las roms de la carpeta excluyendo ficheros .xml
|
|
roms = list_files(folder)
|
|
|
|
# Gestiona la lista de roms
|
|
for rom in roms:
|
|
rom_name = get_file_name_without_extension(rom)
|
|
element = {}
|
|
|
|
# Configuración básica del rom
|
|
element["name"] = rom_name
|
|
element["rom_source"] = os.path.join(folder, rom)
|
|
element["rom_dest"] = os.path.join(DEST_FOLDER, "ROMs", get_system_name(system), rom)
|
|
|
|
# Crear el diccionario "media" con dos claves por entrada
|
|
media_dict = {}
|
|
for key in media_table.keys():
|
|
base_folder = os.path.join(folder, "downloaded_images")
|
|
base_name = f"{rom_name}-{key}"
|
|
|
|
# Llamar a la función para obtener la extensión
|
|
extension = find_file_extension(base_folder, base_name)
|
|
|
|
# Verificar si se encontró la extensión
|
|
if extension:
|
|
media_dict[f"{key}_source"] = os.path.join(base_folder, base_name + extension)
|
|
media_dict[f"{key}_dest"] = os.path.join(DEST_FOLDER, "ES-DE", "downloaded_media", get_system_name(system), media_table[key], rom_name + extension)
|
|
|
|
# Asignar el diccionario "media" al elemento
|
|
element["media"] = media_dict
|
|
|
|
# Añadir el elemento a la lista de ficheros
|
|
file_list.append(element)
|
|
print(system + " - " + rom_name)
|
|
|
|
# Gestiona el fichero "gamelist.xml"
|
|
file_name = "gamelist.xml"
|
|
gamelist = os.path.join(folder, file_name)
|
|
if os.path.isfile(gamelist):
|
|
element = {}
|
|
element["name"] = "gamelist"
|
|
element["rom_source"] = os.path.join(folder, file_name)
|
|
element["rom_dest"] = os.path.join(DEST_FOLDER, "ES-DE", "gamelists", get_system_name(system), file_name)
|
|
file_list.append(element)
|
|
|
|
return file_list
|
|
|
|
|
|
def copy_file(source_path, dest_path):
|
|
"""
|
|
Copia un archivo desde source_path a dest_path, o crea un enlace simbólico
|
|
según el valor de CREATE_SYM_LINKS.
|
|
Si el archivo de destino ya existe, no hace nada.
|
|
Si el archivo tiene una extensión no permitida, no lo copia ni lo enlaza.
|
|
Si el archivo es un .xml, se usa un método especial para copiarlo.
|
|
"""
|
|
# Lista de extensiones no permitidas
|
|
forbidden_extensions = []
|
|
if not GET_VIDEOS:
|
|
forbidden_extensions.append(".mp4")
|
|
|
|
if not source_path or not dest_path:
|
|
print(f"Source o destino inválido: {source_path}, {dest_path}. Saltando...")
|
|
return
|
|
|
|
# Verificar si el archivo tiene una extensión no permitida
|
|
_, extension = os.path.splitext(source_path)
|
|
if extension in forbidden_extensions:
|
|
print(f"Archivo con extensión no permitida ({extension}): {source_path}. Saltando...")
|
|
return
|
|
|
|
# Manejo especial para archivos .xml
|
|
if extension == ".xml":
|
|
copy_xml_file(source_path, dest_path) # Llamar al método especial para XML
|
|
return
|
|
|
|
# Crear el directorio de destino si no existe
|
|
dest_dir = os.path.dirname(dest_path)
|
|
if not os.path.exists(dest_dir):
|
|
os.makedirs(dest_dir)
|
|
print(f"Directorio creado: {dest_dir}")
|
|
|
|
# Verificar si el archivo de destino ya existe
|
|
if os.path.exists(dest_path):
|
|
print(f"El archivo ya existe: {dest_path}. No se realiza la operación.")
|
|
return
|
|
|
|
# Comportamiento según CREATE_SYM_LINKS
|
|
try:
|
|
if CREATE_SYM_LINKS:
|
|
os.symlink(source_path, dest_path) # Crear el enlace simbólico
|
|
print(f"Enlace simbólico creado: {source_path} -> {dest_path}")
|
|
else:
|
|
shutil.copy2(source_path, dest_path) # Copiar el archivo
|
|
print(f"Copiado: {source_path} -> {dest_path}")
|
|
except FileNotFoundError:
|
|
print(f"Archivo fuente no encontrado: {source_path}. Saltando...")
|
|
except Exception as e:
|
|
print(f"Error al realizar la operación con {source_path} a {dest_path}: {e}")
|
|
|
|
|
|
def copy_xml_file(source_path, dest_path):
|
|
"""
|
|
Copia un archivo XML omitiendo las líneas que contienen ciertos textos no deseados.
|
|
"""
|
|
# Lista de textos a omitir
|
|
texts_to_omit = [
|
|
"<boxart>",
|
|
"<boxback>",
|
|
"<cartridge>",
|
|
"<image>",
|
|
"<manual>",
|
|
"<marquee>",
|
|
"<mix>",
|
|
"<screenshot>",
|
|
"<thumbnail />",
|
|
"<video>",
|
|
"<wheel>",
|
|
]
|
|
|
|
# Crear el directorio de destino si no existe
|
|
dest_dir = os.path.dirname(dest_path)
|
|
if not os.path.exists(dest_dir):
|
|
os.makedirs(dest_dir)
|
|
print(f"Directorio creado: {dest_dir}")
|
|
|
|
try:
|
|
# Leer el archivo fuente y escribir solo las líneas permitidas en el archivo destino
|
|
with open(source_path, "r", encoding="utf-8") as source_file, open(dest_path, "w", encoding="utf-8") as dest_file:
|
|
for line in source_file:
|
|
# Si ninguna de las etiquetas a omitir está en la línea, escríbela en el destino
|
|
if not any(text in line for text in texts_to_omit):
|
|
dest_file.write(line)
|
|
|
|
print(f"Archivo XML procesado y copiado: {source_path} -> {dest_path}")
|
|
except FileNotFoundError:
|
|
print(f"Archivo XML fuente no encontrado: {source_path}. Saltando...")
|
|
except Exception as e:
|
|
print(f"Error al procesar el archivo XML {source_path} a {dest_path}: {e}")
|
|
|
|
|
|
def copy_files_with_structure(data):
|
|
"""
|
|
Copia los archivos apuntados por las claves *_source a sus homólogos *_dest.
|
|
Incluye rom_source y rom_dest. Crea las carpetas de destino si no existen.
|
|
"""
|
|
# Manejar archivos de media (claves *_source y *_dest)
|
|
if "media" in data:
|
|
for key, source_path in data["media"].items():
|
|
if key.endswith("_source"):
|
|
# Buscar la clave _dest correspondiente
|
|
dest_key = key.replace("_source", "_dest")
|
|
dest_path = data["media"].get(dest_key)
|
|
copy_file(source_path, dest_path)
|
|
|
|
# Manejar archivo de rom_source -> rom_dest
|
|
if "rom_source" in data and "rom_dest" in data:
|
|
copy_file(data["rom_source"], data["rom_dest"])
|
|
|
|
|
|
def main():
|
|
"""Función principal del programa."""
|
|
file_list = create_file_list()
|
|
for game in file_list:
|
|
copy_files_with_structure(game)
|
|
|
|
# Verifica si este archivo se ejecuta como script principal
|
|
if __name__ == "__main__":
|
|
main()
|