From 54adb653afcdef2bf923e7c61e64d3dd37b2ffff Mon Sep 17 00:00:00 2001 From: Georges-Antoine Assi Date: Fri, 15 Aug 2025 21:57:18 -0400 Subject: [PATCH 1/4] Normalize result names for better merging in search --- backend/endpoints/search.py | 39 +++++++++++++++++-------------------- 1 file changed, 18 insertions(+), 21 deletions(-) diff --git a/backend/endpoints/search.py b/backend/endpoints/search.py index 9799d1bb3..57c6aefa5 100644 --- a/backend/endpoints/search.py +++ b/backend/endpoints/search.py @@ -110,31 +110,28 @@ async def search_rom( merged_dict: dict[str, dict] = {} for igdb_rom in igdb_matched_roms: - igdb_name = igdb_rom.get("name", "") - if igdb_name: - merged_dict[igdb_name] = { - **igdb_rom, - "igdb_url_cover": igdb_rom.pop("url_cover", ""), - **merged_dict.get(igdb_name, {}), - } + igdb_name = meta_igdb_handler.normalize_search_term(igdb_rom.get("name", "")) + merged_dict[igdb_name] = { + **igdb_rom, + "igdb_url_cover": igdb_rom.pop("url_cover", ""), + **merged_dict.get(igdb_name, {}), + } for moby_rom in moby_matched_roms: - moby_name = moby_rom.get("name", "") - if moby_name: - merged_dict[moby_name] = { # type: ignore - **moby_rom, - "moby_url_cover": moby_rom.pop("url_cover", ""), - **merged_dict.get(moby_name, {}), - } + moby_name = meta_moby_handler.normalize_search_term(moby_rom.get("name", "")) + merged_dict[moby_name] = { + **moby_rom, + "moby_url_cover": moby_rom.pop("url_cover", ""), + **merged_dict.get(moby_name, {}), + } for ss_rom in ss_matched_roms: - ss_name = ss_rom.get("name", "") - if ss_name: - merged_dict[ss_name] = { - **ss_rom, - "ss_url_cover": ss_rom.pop("url_cover", ""), - **merged_dict.get(ss_name, {}), - } + ss_name = meta_ss_handler.normalize_search_term(ss_rom.get("name", "")) + merged_dict[ss_name] = { + **ss_rom, + "ss_url_cover": ss_rom.pop("url_cover", ""), + **merged_dict.get(ss_name, {}), + } matched_roms = [ { From 7c3764802fb99d6635903e31a1f10d3745f8775e Mon Sep 17 00:00:00 2001 From: Georges-Antoine Assi Date: Fri, 15 Aug 2025 22:14:48 -0400 Subject: [PATCH 2/4] add sgdb as a cover option --- backend/endpoints/responses/search.py | 8 +- backend/endpoints/search.py | 77 +++++++++++-------- .../__generated__/models/SearchRomSchema.ts | 2 + .../src/components/common/Game/Card/Base.vue | 4 +- .../common/Game/Dialog/MatchRom.vue | 15 +++- 5 files changed, 64 insertions(+), 42 deletions(-) diff --git a/backend/endpoints/responses/search.py b/backend/endpoints/responses/search.py index b59ae8351..ab4c1cb6b 100644 --- a/backend/endpoints/responses/search.py +++ b/backend/endpoints/responses/search.py @@ -6,13 +6,15 @@ class SearchRomSchema(BaseModel): igdb_id: int | None = None moby_id: int | None = None ss_id: int | None = None - slug: str + sgdb_id: int | None = None + platform_id: int name: str - summary: str + slug: str = "" + summary: str = "" igdb_url_cover: str = "" moby_url_cover: str = "" ss_url_cover: str = "" - platform_id: int + sgdb_url_cover: str = "" class SearchCoverSchema(BaseModel): diff --git a/backend/endpoints/search.py b/backend/endpoints/search.py index 57c6aefa5..e70b4d846 100644 --- a/backend/endpoints/search.py +++ b/backend/endpoints/search.py @@ -97,7 +97,11 @@ async def search_rom( moby_matched_roms = [moby_rom] if moby_rom else [] ss_matched_roms = [ss_rom] if ss_rom else [] elif search_by.lower() == "name": - igdb_matched_roms, moby_matched_roms, ss_matched_roms = await asyncio.gather( + ( + igdb_matched_roms, + moby_matched_roms, + ss_matched_roms, + ) = await asyncio.gather( meta_igdb_handler.get_matched_roms_by_name( search_term, get_main_platform_igdb_id(rom.platform) ), @@ -110,44 +114,49 @@ async def search_rom( merged_dict: dict[str, dict] = {} for igdb_rom in igdb_matched_roms: - igdb_name = meta_igdb_handler.normalize_search_term(igdb_rom.get("name", "")) - merged_dict[igdb_name] = { - **igdb_rom, - "igdb_url_cover": igdb_rom.pop("url_cover", ""), - **merged_dict.get(igdb_name, {}), - } + if igdb_rom["igdb_id"]: + igdb_name = meta_igdb_handler.normalize_search_term( + igdb_rom.get("name", "") + ) + merged_dict[igdb_name] = { + **igdb_rom, + "platform_id": rom.platform_id, + "igdb_url_cover": igdb_rom.pop("url_cover", ""), + **merged_dict.get(igdb_name, {}), + } for moby_rom in moby_matched_roms: - moby_name = meta_moby_handler.normalize_search_term(moby_rom.get("name", "")) - merged_dict[moby_name] = { - **moby_rom, - "moby_url_cover": moby_rom.pop("url_cover", ""), - **merged_dict.get(moby_name, {}), - } + if moby_rom["moby_id"]: + moby_name = meta_moby_handler.normalize_search_term( + moby_rom.get("name", "") + ) + merged_dict[moby_name] = { + **moby_rom, + "platform_id": rom.platform_id, + "moby_url_cover": moby_rom.pop("url_cover", ""), + **merged_dict.get(moby_name, {}), + } for ss_rom in ss_matched_roms: - ss_name = meta_ss_handler.normalize_search_term(ss_rom.get("name", "")) - merged_dict[ss_name] = { - **ss_rom, - "ss_url_cover": ss_rom.pop("url_cover", ""), - **merged_dict.get(ss_name, {}), - } - - matched_roms = [ - { - **{ - "slug": "", - "name": "", - "summary": "", - "igdb_url_cover": "", - "moby_url_cover": "", - "ss_url_cover": "", + if ss_rom["ss_id"]: + ss_name = meta_ss_handler.normalize_search_term(ss_rom.get("name", "")) + merged_dict[ss_name] = { + **ss_rom, "platform_id": rom.platform_id, - }, - **item, - } - for item in list(merged_dict.values()) - ] + "ss_url_cover": ss_rom.pop("url_cover", ""), + **merged_dict.get(ss_name, {}), + } + + for name, matched_rom in merged_dict.items(): + sgdb_rom = await meta_sgdb_handler.get_details_by_names([name]) + if sgdb_rom["sgdb_id"]: + merged_dict[name] = { + **matched_rom, + "sgdb_id": sgdb_rom.get("sgdb_id", ""), + "sgdb_url_cover": sgdb_rom.get("url_cover", ""), + } + + matched_roms = list(merged_dict.values()) log.info("Results:") for m_rom in matched_roms: diff --git a/frontend/src/__generated__/models/SearchRomSchema.ts b/frontend/src/__generated__/models/SearchRomSchema.ts index d0dbb297b..e18e28aca 100644 --- a/frontend/src/__generated__/models/SearchRomSchema.ts +++ b/frontend/src/__generated__/models/SearchRomSchema.ts @@ -7,12 +7,14 @@ export type SearchRomSchema = { igdb_id?: (number | null); moby_id?: (number | null); ss_id?: (number | null); + sgdb_id?: (number | null); slug: string; name: string; summary: string; igdb_url_cover?: string; moby_url_cover?: string; ss_url_cover?: string; + sgdb_url_cover?: string; platform_id: number; }; diff --git a/frontend/src/components/common/Game/Card/Base.vue b/frontend/src/components/common/Game/Card/Base.vue index a55db82fd..1f9168a5f 100644 --- a/frontend/src/components/common/Game/Card/Base.vue +++ b/frontend/src/components/common/Game/Card/Base.vue @@ -215,6 +215,7 @@ onBeforeUnmount(() => { : rom.igdb_url_cover || rom.moby_url_cover || rom.ss_url_cover || + rom.sgdb_url_cover || fallbackCoverImage) " :aspect-ratio="computedAspectRatio" @@ -228,7 +229,8 @@ onBeforeUnmount(() => { (!romsStore.isSimpleRom(rom) && !rom.igdb_url_cover && !rom.moby_url_cover && - !rom.ss_url_cover) + !rom.ss_url_cover && + !rom.sgdb_url_cover) " class="translucent-dark text-white" :class=" diff --git a/frontend/src/components/common/Game/Dialog/MatchRom.vue b/frontend/src/components/common/Game/Dialog/MatchRom.vue index cb83a2983..23a0ca137 100644 --- a/frontend/src/components/common/Game/Dialog/MatchRom.vue +++ b/frontend/src/components/common/Game/Dialog/MatchRom.vue @@ -18,7 +18,7 @@ import { getMissingCoverImage } from "@/utils/covers"; type MatchedSource = { url_cover: string | undefined; - name: "IGDB" | "Mobygames" | "Screenscraper"; + name: "IGDB" | "Mobygames" | "Screenscraper" | "SteamGridDB"; logo_path: string; }; @@ -146,27 +146,34 @@ function showSources(matchedRom: SearchRomSchema) { showSelectSource.value = true; selectedMatchRom.value = matchedRom; sources.value = []; - if (matchedRom.igdb_url_cover || matchedRom.igdb_id) { + if (matchedRom.igdb_url_cover) { sources.value.push({ url_cover: matchedRom.igdb_url_cover, name: "IGDB", logo_path: "/assets/scrappers/igdb.png", }); } - if (matchedRom.moby_url_cover || matchedRom.moby_id) { + if (matchedRom.moby_url_cover) { sources.value.push({ url_cover: matchedRom.moby_url_cover, name: "Mobygames", logo_path: "/assets/scrappers/moby.png", }); } - if (matchedRom.ss_url_cover || matchedRom.ss_id) { + if (matchedRom.ss_url_cover) { sources.value.push({ url_cover: matchedRom.ss_url_cover, name: "Screenscraper", logo_path: "/assets/scrappers/ss.png", }); } + if (matchedRom.sgdb_url_cover) { + sources.value.push({ + url_cover: matchedRom.sgdb_url_cover, + name: "SteamGridDB", + logo_path: "/assets/scrappers/sgdb.png", + }); + } if (sources.value.length == 1) { selectedCover.value = sources.value[0]; } From e0d1d1cf23278098bada043f20a05e64cb1a0449 Mon Sep 17 00:00:00 2001 From: Georges-Antoine Assi Date: Fri, 15 Aug 2025 22:30:13 -0400 Subject: [PATCH 3/4] run sgdb in parallel --- backend/endpoints/search.py | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/backend/endpoints/search.py b/backend/endpoints/search.py index e70b4d846..02ef4aac0 100644 --- a/backend/endpoints/search.py +++ b/backend/endpoints/search.py @@ -14,7 +14,7 @@ from handler.metadata import ( ) from handler.metadata.igdb_handler import IGDB_API_ENABLED, IGDBRom from handler.metadata.moby_handler import MOBY_API_ENABLED, MobyGamesRom -from handler.metadata.sgdb_handler import STEAMGRIDDB_API_ENABLED +from handler.metadata.sgdb_handler import STEAMGRIDDB_API_ENABLED, SGDBRom from handler.metadata.ss_handler import SS_API_ENABLED, SSRom from handler.scan_handler import get_main_platform_igdb_id from logger.formatter import BLUE, CYAN @@ -147,11 +147,18 @@ async def search_rom( **merged_dict.get(ss_name, {}), } - for name, matched_rom in merged_dict.items(): - sgdb_rom = await meta_sgdb_handler.get_details_by_names([name]) + async def get_sgdb_rom(name: str) -> tuple[str, SGDBRom]: + return name, await meta_sgdb_handler.get_details_by_names([name]) + + # Only get SteamGridDB details for first 5 results + sgdb_roms = await asyncio.gather( + *[get_sgdb_rom(name) for name in list(merged_dict.keys())[:5]] + ) + + for name, sgdb_rom in sgdb_roms: if sgdb_rom["sgdb_id"]: merged_dict[name] = { - **matched_rom, + **merged_dict[name], "sgdb_id": sgdb_rom.get("sgdb_id", ""), "sgdb_url_cover": sgdb_rom.get("url_cover", ""), } From c742e8ff9d8f227e4b15889d7fb45c15b67012fe Mon Sep 17 00:00:00 2001 From: Georges-Antoine Assi Date: Fri, 15 Aug 2025 22:48:57 -0400 Subject: [PATCH 4/4] dont remove articles normalize name --- backend/endpoints/search.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/backend/endpoints/search.py b/backend/endpoints/search.py index 02ef4aac0..a22e1f9fa 100644 --- a/backend/endpoints/search.py +++ b/backend/endpoints/search.py @@ -116,7 +116,8 @@ async def search_rom( for igdb_rom in igdb_matched_roms: if igdb_rom["igdb_id"]: igdb_name = meta_igdb_handler.normalize_search_term( - igdb_rom.get("name", "") + igdb_rom.get("name", ""), + remove_articles=False, ) merged_dict[igdb_name] = { **igdb_rom, @@ -128,7 +129,8 @@ async def search_rom( for moby_rom in moby_matched_roms: if moby_rom["moby_id"]: moby_name = meta_moby_handler.normalize_search_term( - moby_rom.get("name", "") + moby_rom.get("name", ""), + remove_articles=False, ) merged_dict[moby_name] = { **moby_rom, @@ -139,7 +141,10 @@ async def search_rom( for ss_rom in ss_matched_roms: if ss_rom["ss_id"]: - ss_name = meta_ss_handler.normalize_search_term(ss_rom.get("name", "")) + ss_name = meta_ss_handler.normalize_search_term( + ss_rom.get("name", ""), + remove_articles=False, + ) merged_dict[ss_name] = { **ss_rom, "platform_id": rom.platform_id, @@ -150,9 +155,8 @@ async def search_rom( async def get_sgdb_rom(name: str) -> tuple[str, SGDBRom]: return name, await meta_sgdb_handler.get_details_by_names([name]) - # Only get SteamGridDB details for first 5 results sgdb_roms = await asyncio.gather( - *[get_sgdb_rom(name) for name in list(merged_dict.keys())[:5]] + *[get_sgdb_rom(name) for name in list(merged_dict.keys())] ) for name, sgdb_rom in sgdb_roms: