fix scanning multi file games with ssfr

This commit is contained in:
Georges-Antoine Assi
2025-10-31 10:50:51 -04:00
parent 7fa978c57d
commit f8b0ae63a1
7 changed files with 72 additions and 37 deletions

View File

@@ -270,10 +270,6 @@ async def _identify_rom(
)
)
# Silly checks to make the type checker happy
if not rom:
return
# Build rom files object before scanning
should_update_files = _should_get_rom_files(
scan_type=scan_type, rom=rom, newly_added=newly_added, roms_ids=roms_ids

View File

@@ -259,7 +259,7 @@ class FSRomsHandler(FSHandler):
return [f for f in roms if f not in filtered_files]
def _build_rom_file(
self, rom_path: Path, file_name: str, file_hash: FileHash
self, rom: Rom, rom_path: Path, file_name: str, file_hash: FileHash
) -> RomFile:
# Absolute path to roms
abs_file_path = Path(self.base_path, rom_path, file_name)
@@ -275,6 +275,8 @@ class FSRomsHandler(FSHandler):
)
return RomFile(
rom=rom,
rom_id=rom.id,
file_name=file_name,
file_path=str(rom_path),
file_size_bytes=os.stat(abs_file_path).st_size,
@@ -380,9 +382,10 @@ class FSRomsHandler(FSHandler):
rom_files.append(
self._build_rom_file(
f_path.relative_to(self.base_path),
file_name,
file_hash,
rom=rom,
rom_path=f_path.relative_to(self.base_path),
file_name=file_name,
file_hash=file_hash,
)
)
elif hashable_platform:
@@ -417,7 +420,12 @@ class FSRomsHandler(FSHandler):
),
)
rom_files.append(
self._build_rom_file(Path(rel_roms_path), rom.fs_name, file_hash)
self._build_rom_file(
rom=rom,
rom_path=Path(rel_roms_path),
file_name=rom.fs_name,
file_hash=file_hash,
)
)
else:
file_hash = FileHash(
@@ -426,7 +434,12 @@ class FSRomsHandler(FSHandler):
sha1_hash="",
)
rom_files.append(
self._build_rom_file(Path(rel_roms_path), rom.fs_name, file_hash)
self._build_rom_file(
rom=rom,
rom_path=Path(rel_roms_path),
file_name=rom.fs_name,
file_hash=file_hash,
)
)
return (

View File

@@ -53,7 +53,7 @@ class HasheousRom(BaseRom):
hasheous_metadata: NotRequired[HasheousMetadata]
ACCEPTABLE_FILE_EXTENSIONS_BY_PLATFORM_SLUG = {"dc": ["cue"]}
ACCEPTABLE_FILE_EXTENSIONS_BY_PLATFORM_SLUG = {UPS.DC: ["cue", "bin"]}
def extract_metadata_from_igdb_rom(rom: dict[str, Any]) -> IGDBMetadata:
@@ -238,13 +238,12 @@ class HasheousHandler(MetadataHandler):
filtered_files = [
file
for file in files
if file.file_size_bytes is not None
and file.file_size_bytes > 0
if file.file_size_bytes > 0
and file.is_top_level
and (
file.file_extension
in ACCEPTABLE_FILE_EXTENSIONS_BY_PLATFORM_SLUG[platform_slug]
if platform_slug in ACCEPTABLE_FILE_EXTENSIONS_BY_PLATFORM_SLUG
in ACCEPTABLE_FILE_EXTENSIONS_BY_PLATFORM_SLUG[UPS(platform_slug)]
if UPS(platform_slug) in ACCEPTABLE_FILE_EXTENSIONS_BY_PLATFORM_SLUG
else True
)
]

View File

@@ -121,11 +121,7 @@ class PlaymatchHandler(MetadataHandler):
return PlaymatchRomMatch(igdb_id=None)
first_file = next(
(
file
for file in files
if file.file_size_bytes is not None and file.file_size_bytes > 0
),
(file for file in files if file.file_size_bytes > 0),
None,
)
if first_file is None:

View File

@@ -14,7 +14,7 @@ from config.config_manager import MetadataMediaType
from config.config_manager import config_manager as cm
from handler.filesystem import fs_resource_handler
from logger.logger import log
from models.rom import Rom
from models.rom import Rom, RomFile
from .base_handler import (
PS2_OPL_REGEX,
@@ -128,6 +128,12 @@ ARCADE_SS_IDS: Final = [
# Regex to detect ScreenScraper ID tags in filenames like (ssfr-12345)
SS_TAG_REGEX = re.compile(r"\(ssfr-(\d+)\)", re.IGNORECASE)
ACCEPTABLE_FILE_EXTENSIONS_BY_PLATFORM_SLUG = {
UPS.DC: ["cue", "chd", "gdi", "cdi"],
UPS.SEGACD: ["cue", "chd", "bin"],
UPS.NGC: ["rvz", "iso", "gcz"],
}
class SSPlatform(TypedDict):
slug: str
@@ -516,17 +522,36 @@ class SSHandler(MetadataHandler):
name=platform["name"],
)
async def lookup_rom(self, rom: Rom, rom_attrs: dict, platform_ss_id: int) -> SSRom:
async def lookup_rom(
self, rom: Rom, platform_ss_id: int, files: list[RomFile]
) -> SSRom:
if not self.is_enabled():
return SSRom(ss_id=None)
if not platform_ss_id:
return SSRom(ss_id=None)
md5_hash = rom_attrs["md5_hash"]
sha1_hash = rom_attrs["sha1_hash"]
crc_hash = rom_attrs["crc_hash"]
fs_size_bytes = rom_attrs["fs_size_bytes"]
filtered_files = [
file
for file in files
if file.file_size_bytes > 0
and file.is_top_level
and (
file.file_extension
in ACCEPTABLE_FILE_EXTENSIONS_BY_PLATFORM_SLUG[UPS(rom.platform_slug)]
if UPS(rom.platform_slug) in ACCEPTABLE_FILE_EXTENSIONS_BY_PLATFORM_SLUG
else True
)
]
first_file = max(filtered_files, key=lambda f: f.file_size_bytes, default=None)
if first_file is None:
return SSRom(ss_id=None)
md5_hash = first_file.md5_hash
sha1_hash = first_file.sha1_hash
crc_hash = first_file.crc_hash
fs_size_bytes = first_file.file_size_bytes
if not (md5_hash or sha1_hash or crc_hash):
log.info(

View File

@@ -556,18 +556,21 @@ async def scan_rom(
)
)
):
hash_lookup = await meta_ss_handler.lookup_rom(
rom, rom_attrs, platform.ss_id
)
if hash_lookup.get("ss_id"):
return hash_lookup
# Use the ID to refetch metadata
if scan_type == ScanType.UPDATE and rom.ss_id:
return await meta_ss_handler.get_rom_by_id(rom, rom.ss_id)
else:
return await meta_ss_handler.get_rom(
rom, rom_attrs["fs_name"], platform_ss_id=platform.ss_id
)
# Use the file hashes for lookup
game_by_hash = await meta_ss_handler.lookup_rom(
rom, platform.ss_id, fs_rom["files"]
)
if game_by_hash.get("ss_id"):
return game_by_hash
# Fallback to the filename
return await meta_ss_handler.get_rom(
rom, rom_attrs["fs_name"], platform_ss_id=platform.ss_id
)
return SSRom(ss_id=None)

View File

@@ -117,6 +117,9 @@ class RomFile(BaseModel):
f"{self.rom.full_path}/", ".hidden/" if hidden_folder else ""
)
def __repr__(self) -> str:
return f"{self.file_name} ({self.id} -> {self.rom_id})"
class RomMetadata(BaseModel):
__tablename__ = "roms_metadata"
@@ -407,7 +410,7 @@ class Rom(BaseModel):
self._is_identifying = value
def __repr__(self) -> str:
return self.fs_name
return f"{self.fs_name} ({self.id})"
class RomUserStatus(enum.StrEnum):