diff --git a/functions/all.ps1 b/functions/all.ps1 index 5f7901a3..7f3ce7c2 100644 --- a/functions/all.ps1 +++ b/functions/all.ps1 @@ -50,6 +50,7 @@ if (-not "$emulationPath") { . "$env:APPDATA\EmuDeck\backend\functions\cloudSyncHealth.ps1" #. "$env:APPDATA\EmuDeck\backend\functions\ToolScripts\emuDeckNetplay.ps1" . "$env:APPDATA\EmuDeck\backend\functions\ToolScripts\emuDeckMigration.ps1" +. "$env:APPDATA\EmuDeck\backend\functions\generateGameLists.ps1" #Android . "$env:APPDATA\EmuDeck\backend\android\functions\all.ps1" diff --git a/functions/generateGameLists.ps1 b/functions/generateGameLists.ps1 new file mode 100644 index 00000000..15f03ae6 --- /dev/null +++ b/functions/generateGameLists.ps1 @@ -0,0 +1,154 @@ +function generateGameListsJson { + param ( + [string]$romsPath + ) + + # Ejecuta el script de Python para generar la lista de juegos + python "$HOME\.config\EmuDeck\backend\tools\generate_game_lists.py" $romsPath + + # Muestra el contenido del archivo roms_games.json + Get-Content "$HOME\emudeck\cache\roms_games.json" + + # Comprueba si .romlibrary_first existe y ejecuta la lógica de generación de arte + if (Test-Path "$HOME\emudeck\cache\.romlibrary_first") { + Start-Process -NoNewWindow -FilePath "generateGameLists_artwork" -ArgumentList 0 + } + else { + for ($i = 1; $i -le 5; $i++) { + generateGameLists_artwork $i + Start-Sleep -Seconds 5 + } + # Crea el archivo .romlibrary_first + New-Item -ItemType File -Path "$HOME\emudeck\cache\.romlibrary_first" | Out-Null + } +} + + +function generateGameLists_artwork { + param ( + [int]$number_log + ) + + # Define las rutas necesarias + $cacheFolder = "$HOME\emudeck\cache\" + $logFolder = "$HOME\emudeck\logs\" + $jsonFile = "$cacheFolder\roms_games.json" + $logFileName = "$logFolder\library_$number_log.log" + $accountFolder = (Get-ChildItem -Directory "$HOME\.steam\steam\userdata" | Sort-Object LastWriteTime -Descending | Select-Object -First 1).FullName + $destFolder = "$accountFolder\config\grid\emudeck\" + $processedGames = @{} + + # Crea los directorios necesarios + New-Item -ItemType Directory -Force -Path $cacheFolder | Out-Null + New-Item -ItemType Directory -Force -Path $destFolder | Out-Null + "" | Out-File -Encoding utf8 $logFileName + + # Lee el contenido del archivo JSON + $jsonContent = Get-Content $jsonFile | Out-String | ConvertFrom-Json + + # Determina las plataformas + if ($number_log -eq 1) { + $platforms = $jsonContent | ForEach-Object { $_.id } + } else { + $platforms = ($jsonContent | ForEach-Object { $_.id }) | Get-Random -Count ($jsonContent.Count) + } + + foreach ($platform in $platforms) { + "`nProcessing platform: $platform" | Out-File -Append -Encoding utf8 $logFileName + + if ($number_log -eq 1) { + $games = $jsonContent | Where-Object { $_.id -eq $platform } | ForEach-Object { $_.games.name } + } else { + $games = ($jsonContent | Where-Object { $_.id -eq $platform } | ForEach-Object { $_.games.name }) | Get-Random -Count ($games.Count) + } + + $downloadArray = @() + $downloadDestPaths = @() + + foreach ($game in $games) { + $fileToCheck = "$destFolder$($game -replace ' ', '_').jpg" + if (!(Test-Path $fileToCheck) -and -not $processedGames.ContainsKey($game)) { + "`nGAME: $game" | Out-File -Append -Encoding utf8 $logFileName + + # Procesamiento fuzzy + $fuzzygame = python "$HOME\.config\EmuDeck\backend\tools\fuzzy_search_rom.py" $game | Out-String + $fuzzygame = $fuzzygame -replace '[\s:./&!]', '' + "`nFUZZY: $fuzzygame" | Out-File -Append -Encoding utf8 $logFileName + + # Realiza la consulta de imagen + Invoke-WebRequest -Uri "https://bot.emudeck.com/steamdbimg.php?name=$fuzzygame" -OutFile "$cacheFolder\response.json" + $response = Get-Content "$cacheFolder\response.json" | ConvertFrom-Json + $gameImgUrl = $response.img + $destPath = "$destFolder$game.jpg" + + if (!(Test-Path $destPath) -and $gameImgUrl -ne "null") { + "`nAdded to the list: $gameImgUrl" | Out-File -Append -Encoding utf8 $logFileName + $downloadArray += $gameImgUrl + $downloadDestPaths += $destPath + $processedGames[$game] = $true + } else { + Invoke-WebRequest -Uri "https://bot.emudeck.com/steamdbimg.php?name=$game" -OutFile "$cacheFolder\response.json" + $response = Get-Content "$cacheFolder\response.json" | ConvertFrom-Json + $gameImgUrl = $response.img + $destPath = "$destFolder$game.jpg" + + if ($gameImgUrl -ne "null") { + "`nAdded to the list (NO FUZZY): $gameImgUrl" | Out-File -Append -Encoding utf8 $logFileName + $downloadArray += $gameImgUrl + $downloadDestPaths += $destPath + $processedGames[$game] = $true + } else { + "`n - No picture" | Out-File -Append -Encoding utf8 $logFileName + } + } + } + + # Descargar en lotes de 10 + if ($downloadArray.Count -ge 10) { + "`nStart batch" | Out-File -Append -Encoding utf8 $logFileName + for ($i = 0; $i -lt $downloadArray.Count; $i++) { + Start-Job -ScriptBlock { + param ($url, $destPath) + Invoke-WebRequest -Uri $url -OutFile $destPath + } -ArgumentList $downloadArray[$i], $downloadDestPaths[$i] + } + Get-Job | Wait-Job | Remove-Job + "`nCompleted batch" | Out-File -Append -Encoding utf8 $logFileName + $downloadArray = @() + $downloadDestPaths = @() + } + } + + # Descargar imágenes restantes + if ($downloadArray.Count -ne 0) { + for ($i = 0; $i -lt $downloadArray.Count; $i++) { + Start-Job -ScriptBlock { + param ($url, $destPath) + Invoke-WebRequest -Uri $url -OutFile $destPath + } -ArgumentList $downloadArray[$i], $downloadDestPaths[$i] + } + Get-Job | Wait-Job | Remove-Job + } + + "`nCompleted search for platform: $platform" | Out-File -Append -Encoding utf8 $logFileName + } +} + + +function saveImage { + param ( + [string]$url, + [string]$name + ) + + # Define la carpeta de destino + $accountFolder = (Get-ChildItem -Directory "$HOME\.steam\steam\userdata" | Sort-Object LastWriteTime -Descending | Select-Object -First 1).FullName + $destFolder = "$accountFolder\config\grid\emudeck" + $destPath = "$destFolder\$name.jpg" + + # Crea el directorio de destino si no existe + New-Item -ItemType Directory -Force -Path $destFolder | Out-Null + + # Descarga la imagen desde la URL proporcionada + Invoke-WebRequest -Uri $url -OutFile $destPath -Quiet +} diff --git a/tools/retroLibrary/fuzzy_search_rom.py b/tools/retroLibrary/fuzzy_search_rom.py new file mode 100644 index 00000000..37c48a13 --- /dev/null +++ b/tools/retroLibrary/fuzzy_search_rom.py @@ -0,0 +1,79 @@ +import urllib.request +import json +import sys +import os +import subprocess +from difflib import SequenceMatcher +from datetime import datetime, timedelta + +def similar(a, b): + return SequenceMatcher(None, a, b).ratio() + +def find_best_match(search_title, games): + best_match = None + highest_similarity = 0 + + for game in games: + similarity = similar(search_title, game) # Asegúrate de que estás comparando con el nombre del juego + if similarity > highest_similarity: + highest_similarity = similarity + best_match = game # Devolver solo el nombre del juego o el objeto completo si prefieres + + return best_match + +def is_file_older_than(file_path, days): + file_time = datetime.fromtimestamp(os.path.getmtime(file_path)) + return datetime.now() - file_time > timedelta(days=days) + +# URL del JSON +url = "https://steamgriddb.com/api/games" + +# Título para buscar +search_title = sys.argv[1] +#print(f"{search_title}") +#sys.exit() + +# Directorio para guardar el archivo JSON +home_dir = os.path.expanduser("~") +emudeck_dir = os.path.join(home_dir, "emudeck") +os.makedirs(emudeck_dir, exist_ok=True) +json_file_path = os.path.join(emudeck_dir, "games.json") + +# Descargar o cargar el JSON +if not os.path.exists(json_file_path) or is_file_older_than(json_file_path, 5): + + bash_command = 'wget --user-agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36" "https://steamgriddb.com/api/games" -O "$HOME/emudeck/games.json"' + try: + result = subprocess.run(bash_command, shell=True, check=True, text=True, capture_output=True) + print("Salida del comando:", result.stdout) + except subprocess.CalledProcessError as e: + print(f"Ocurrió un error al ejecutar el comando: {e}") + +else: + # Cargar el JSON desde el disco duro + with open(json_file_path, "r") as json_file: + data = json_file.read() + +# Intentar cargar el JSON +try: + json_data = json.loads(data) +except json.JSONDecodeError as e: + print(f"Error al decodificar JSON: {e}") + json_data = {} + +# Asegúrate de que esta parte esté adaptada a la estructura real del JSON +if isinstance(json_data, list): + games = [game for game in json_data if "name" in game] +elif isinstance(json_data, dict) and 'games' in json_data: + games = [game for game in json_data['games']] +else: + print("No se encontraron juegos en el JSON o la estructura no es la esperada.") + games = [] + +# Buscar el título más parecido +if games: + best_match = find_best_match(search_title, games) + # Mostrar el resultado + print(f"{best_match}") +else: + print("null") diff --git a/tools/retroLibrary/generate_game_lists.py b/tools/retroLibrary/generate_game_lists.py new file mode 100644 index 00000000..0630037f --- /dev/null +++ b/tools/retroLibrary/generate_game_lists.py @@ -0,0 +1,126 @@ +import os +import json +import sys +import re + +def generate_game_lists(roms_path): + def collect_game_data(system_dir, extensions): + game_data = [] + for root, _, files in os.walk(system_dir): + for file in files: + file_path = os.path.join(root, file) + if os.path.islink(file_path): + continue + + filename = os.path.basename(file) + extension = filename.split('.')[-1] + name = '.'.join(filename.split('.')[:-1]) + if extension in extensions: + if "wiiu" in system_dir: + if extension == "wux": + name = name + elif extension == "wua": + name = name + else: + parts = root.split(os.sep) + if len(parts) >= 2: + name = parts[-2] + else: + name = name + + if name == "roms": + name = name + + if name == "wiiu": + name = parts[-1] + + if "ps3" in system_dir: + parts = root.split(os.sep) + if len(parts) >= 3: + name = parts[-3] + else: + name = name + + if name == "roms": + name = name + + if name == "ps3": + name = parts[-1] + + + + name_cleaned = re.sub(r'\(.*?\)', '', name) + name_cleaned = re.sub(r'\[.*?\]', '', name_cleaned) + name_cleaned = name_cleaned.strip() + + name_cleaned = name_cleaned.replace(' ', '_') + name_cleaned = name_cleaned.replace('-', '_') + name_cleaned = re.sub(r'_+', '_', name_cleaned) + name_cleaned = name_cleaned.replace('+', '') + name_cleaned = name_cleaned.replace('&', '') + name_cleaned = name_cleaned.replace('!', '') + name_cleaned = name_cleaned.replace("'", '') + name_cleaned = name_cleaned.replace('.', '') + name_cleaned_pegasus = name.replace(',_', ',') + + clean_name = name_cleaned + game_img = f"/customimages/emudeck/{clean_name}.jpg" + game_info = { + "name": clean_name, + "filename": file_path, + "file": name_cleaned_pegasus, + "img": game_img + } + game_data.append(game_info) + game_data_sorted = sorted(game_data, key=lambda x: x['name']) + return game_data_sorted + + roms_dir = roms_path + valid_system_dirs = [] + + for system_dir in os.listdir(roms_dir): + if system_dir == "xbox360": + system_dir = "xbox360/roms" + #if system_dir == "wiiu": + # system_dir = "wiiu/roms" + full_path = os.path.join(roms_dir, system_dir) + if os.path.isdir(full_path) and not os.path.islink(full_path) and os.path.isfile(os.path.join(full_path, 'metadata.txt')): + file_count = sum([len(files) for r, d, files in os.walk(full_path) if not os.path.islink(r)]) + if file_count > 2: + valid_system_dirs.append(full_path) + + game_list = [] + + for system_dir in valid_system_dirs: + if any(x in system_dir for x in ["/model2", "/genesiswide", "/mame", "/emulators", "/desktop"]): + continue + + with open(os.path.join(system_dir, 'metadata.txt')) as f: + metadata = f.read() + collection = next((line.split(':')[1].strip() for line in metadata.splitlines() if line.startswith('collection:')), '') + shortname = next((line.split(':')[1].strip() for line in metadata.splitlines() if line.startswith('shortname:')), '') + launcher = next((line.split(':', 1)[1].strip() for line in metadata.splitlines() if line.startswith('launch:')), '').replace('"', '\\"') + extensions = next((line.split(':')[1].strip().replace(',', ' ') for line in metadata.splitlines() if line.startswith('extensions:')), '').split() + + games = collect_game_data(system_dir, extensions) + if games: + system_info = { + "title": collection, + "id": shortname, + "launcher": launcher, + "games": games + } + game_list.append(system_info) + game_list_sorted = sorted(game_list, key=lambda x: x['title']) + + + json_output = json.dumps(game_list_sorted, indent=4) + home_directory = os.path.expanduser("~") + output_file = os.path.join(home_directory, 'emudeck', 'cache', 'roms_games.json') + os.makedirs(os.path.dirname(output_file), exist_ok=True) + with open(output_file, 'w') as f: + f.write(json_output) + +roms_path = sys.argv[1] + +generate_game_lists(f"{roms_path}")