diff --git a/backend/endpoints/responses/platform.py b/backend/endpoints/responses/platform.py index 4c07d3301..c9f08a2c8 100644 --- a/backend/endpoints/responses/platform.py +++ b/backend/endpoints/responses/platform.py @@ -31,6 +31,8 @@ class PlatformSchema(BaseModel): created_at: datetime updated_at: datetime fs_size_bytes: int + is_unidentified: bool + is_identified: bool class Config: from_attributes = True diff --git a/backend/endpoints/responses/rom.py b/backend/endpoints/responses/rom.py index 754706546..7076be385 100644 --- a/backend/endpoints/responses/rom.py +++ b/backend/endpoints/responses/rom.py @@ -8,6 +8,7 @@ from endpoints.responses.assets import SaveSchema, ScreenshotSchema, StateSchema from endpoints.responses.collection import CollectionSchema from fastapi import Request from handler.metadata.igdb_handler import IGDBMetadata +from handler.metadata.launchbox_handler import LaunchboxMetadata from handler.metadata.moby_handler import MobyMetadata from handler.metadata.ra_handler import RAMetadata from handler.metadata.ss_handler import SSMetadata @@ -38,6 +39,11 @@ RomRAMetadata = TypedDict( # type: ignore[misc] dict((k, NotRequired[v]) for k, v in get_type_hints(RAMetadata).items()), total=False, ) +RomLaunchboxMetadata = TypedDict( # type: ignore[misc] + "RomLaunchboxMetadata", + dict((k, NotRequired[v]) for k, v in get_type_hints(LaunchboxMetadata).items()), + total=False, +) def rom_user_schema_factory() -> RomUserSchema: @@ -173,6 +179,7 @@ class RomSchema(BaseModel): moby_id: int | None ss_id: int | None ra_id: int | None + launchbox_id: int | None platform_id: int platform_slug: str @@ -199,6 +206,7 @@ class RomSchema(BaseModel): igdb_metadata: RomIGDBMetadata | None moby_metadata: RomMobyMetadata | None ss_metadata: RomSSMetadata | None + launchbox_metadata: RomLaunchboxMetadata | None path_cover_small: str | None path_cover_large: str | None @@ -209,6 +217,7 @@ class RomSchema(BaseModel): url_manual: str | None is_unidentified: bool + is_identified: bool revision: str | None regions: list[str] diff --git a/backend/endpoints/rom.py b/backend/endpoints/rom.py index e5a849d3a..0c2f0d693 100644 --- a/backend/endpoints/rom.py +++ b/backend/endpoints/rom.py @@ -178,7 +178,7 @@ def get_roms( favourites_only (bool, optional): Filter only favourite roms. Defaults to False. duplicates_only (bool, optional): Filter only duplicate roms. Defaults to False. playables_only (bool, optional): Filter only playable roms by emulatorjs. Defaults to False. - group_by_meta_id (bool, optional): Group roms by igdb/moby/ssrf ID. Defaults to False. + group_by_meta_id (bool, optional): Group roms by igdb/moby/ssrf/launchbox ID. Defaults to False. selected_genre (str, optional): Filter by genre. Defaults to None. selected_franchise (str, optional): Filter by franchise. Defaults to None. selected_collection (str, optional): Filter by collection. Defaults to None. @@ -524,6 +524,7 @@ async def update_rom( "moby_id": None, "ss_id": None, "ra_id": None, + "launchbox_id": None, "name": rom.fs_name, "summary": "", "url_screenshots": [], @@ -537,6 +538,7 @@ async def update_rom( "moby_metadata": {}, "ss_metadata": {}, "ra_metadata": {}, + "launchbox_metadata": {}, "revision": "", }, ) @@ -551,6 +553,7 @@ async def update_rom( "igdb_id": data.get("igdb_id", rom.igdb_id), "moby_id": data.get("moby_id", rom.moby_id), "ss_id": data.get("ss_id", rom.ss_id), + "launchbox_id": data.get("launchbox_id", rom.launchbox_id), } if ( diff --git a/backend/endpoints/sockets/scan.py b/backend/endpoints/sockets/scan.py index ac71151cf..734430813 100644 --- a/backend/endpoints/sockets/scan.py +++ b/backend/endpoints/sockets/scan.py @@ -127,7 +127,7 @@ def _should_scan_rom(scan_type: ScanType, rom: Rom | None, roms_ids: list[str]) rom and ( (scan_type == ScanType.UNIDENTIFIED and rom.is_unidentified) - or (scan_type == ScanType.PARTIAL and rom.is_partially_identified) + or (scan_type == ScanType.PARTIAL and rom.is_identified) or (rom.id in roms_ids) ) ) diff --git a/backend/models/platform.py b/backend/models/platform.py index 535bf9bf2..2779d1d37 100644 --- a/backend/models/platform.py +++ b/backend/models/platform.py @@ -53,6 +53,18 @@ class Platform(BaseModel): def __repr__(self) -> str: return self.name + @property + def is_unidentified(self) -> bool: + return not self.igdb_id and not self.moby_id and not self.ss_id + + @property + def is_identified(self) -> bool: + return not self.is_unidentified + + @property + def is_fully_identified(self) -> bool: + return bool(self.igdb_id) and bool(self.moby_id) and bool(self.ss_id) + @cached_property def fs_size_bytes(self) -> int: from handler.database import db_stats_handler diff --git a/backend/models/rom.py b/backend/models/rom.py index 349b54b73..03d7e4074 100644 --- a/backend/models/rom.py +++ b/backend/models/rom.py @@ -311,12 +311,16 @@ class Rom(BaseModel): @property def is_unidentified(self) -> bool: return ( - not self.igdb_id and not self.moby_id and not self.ss_id and not self.ra_id + not self.igdb_id + and not self.moby_id + and not self.ss_id + and not self.ra_id + and not self.launchbox_id ) @property - def is_partially_identified(self) -> bool: - return not self.is_unidentified and not self.is_fully_identified + def is_identified(self) -> bool: + return not self.is_unidentified @property def is_fully_identified(self) -> bool: @@ -325,6 +329,7 @@ class Rom(BaseModel): and bool(self.moby_id) and bool(self.ss_id) and bool(self.ra_id) + and bool(self.launchbox_id) ) def has_m3u_file(self) -> bool: diff --git a/frontend/assets/scrappers/launchbox.png b/frontend/assets/scrappers/launchbox.png new file mode 100644 index 000000000..c3d37561e Binary files /dev/null and b/frontend/assets/scrappers/launchbox.png differ diff --git a/frontend/assets/scrappers/sgdb.png b/frontend/assets/scrappers/sgdb.png index 3a2899dd2..21d61c346 100644 Binary files a/frontend/assets/scrappers/sgdb.png and b/frontend/assets/scrappers/sgdb.png differ diff --git a/frontend/assets/scrappers/ss.png b/frontend/assets/scrappers/ss.png index 0faf0fe0a..2969af86c 100644 Binary files a/frontend/assets/scrappers/ss.png and b/frontend/assets/scrappers/ss.png differ diff --git a/frontend/src/__generated__/index.ts b/frontend/src/__generated__/index.ts index 76dc9a4be..aafffa5ee 100644 --- a/frontend/src/__generated__/index.ts +++ b/frontend/src/__generated__/index.ts @@ -40,6 +40,7 @@ export type { Role } from './models/Role'; export type { RomFileCategory } from './models/RomFileCategory'; export type { RomFileSchema } from './models/RomFileSchema'; export type { RomIGDBMetadata } from './models/RomIGDBMetadata'; +export type { RomLaunchboxMetadata } from './models/RomLaunchboxMetadata'; export type { RomMetadataSchema } from './models/RomMetadataSchema'; export type { RomMobyMetadata } from './models/RomMobyMetadata'; export type { RomRAMetadata } from './models/RomRAMetadata'; diff --git a/frontend/src/__generated__/models/DetailedRomSchema.ts b/frontend/src/__generated__/models/DetailedRomSchema.ts index 0a31860b9..7b3373530 100644 --- a/frontend/src/__generated__/models/DetailedRomSchema.ts +++ b/frontend/src/__generated__/models/DetailedRomSchema.ts @@ -5,6 +5,7 @@ import type { CollectionSchema } from './CollectionSchema'; import type { RomFileSchema } from './RomFileSchema'; import type { RomIGDBMetadata } from './RomIGDBMetadata'; +import type { RomLaunchboxMetadata } from './RomLaunchboxMetadata'; import type { RomMetadataSchema } from './RomMetadataSchema'; import type { RomMobyMetadata } from './RomMobyMetadata'; import type { RomRAMetadata } from './RomRAMetadata'; @@ -22,6 +23,7 @@ export type DetailedRomSchema = { moby_id: (number | null); ss_id: (number | null); ra_id: (number | null); + launchbox_id: (number | null); platform_id: number; platform_slug: string; platform_fs_slug: string; @@ -43,6 +45,7 @@ export type DetailedRomSchema = { igdb_metadata: (RomIGDBMetadata | null); moby_metadata: (RomMobyMetadata | null); ss_metadata: (RomSSMetadata | null); + launchbox_metadata: (RomLaunchboxMetadata | null); path_cover_small: (string | null); path_cover_large: (string | null); url_cover: (string | null); @@ -50,6 +53,7 @@ export type DetailedRomSchema = { path_manual: (string | null); url_manual: (string | null); is_unidentified: boolean; + is_identified: boolean; revision: (string | null); regions: Array; languages: Array; diff --git a/frontend/src/__generated__/models/PlatformSchema.ts b/frontend/src/__generated__/models/PlatformSchema.ts index 86120701e..0bcfe9cc4 100644 --- a/frontend/src/__generated__/models/PlatformSchema.ts +++ b/frontend/src/__generated__/models/PlatformSchema.ts @@ -27,6 +27,8 @@ export type PlatformSchema = { created_at: string; updated_at: string; fs_size_bytes: number; + is_unidentified: boolean; + is_identified: boolean; readonly display_name: string; }; diff --git a/frontend/src/__generated__/models/RomLaunchboxMetadata.ts b/frontend/src/__generated__/models/RomLaunchboxMetadata.ts new file mode 100644 index 000000000..e1e823113 --- /dev/null +++ b/frontend/src/__generated__/models/RomLaunchboxMetadata.ts @@ -0,0 +1,19 @@ +/* generated using openapi-typescript-codegen -- do not edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +export type RomLaunchboxMetadata = { + release_date?: string; + max_players?: number; + release_type?: string; + cooperative?: boolean; + video_url?: string; + community_rating?: number; + community_rating_count?: number; + wikipedia_url?: string; + esrb?: string; + genres?: Array; + developer?: string; + publisher?: string; +}; + diff --git a/frontend/src/__generated__/models/SimpleRomSchema.ts b/frontend/src/__generated__/models/SimpleRomSchema.ts index da57242e9..a2e368f16 100644 --- a/frontend/src/__generated__/models/SimpleRomSchema.ts +++ b/frontend/src/__generated__/models/SimpleRomSchema.ts @@ -4,6 +4,7 @@ /* eslint-disable */ import type { RomFileSchema } from './RomFileSchema'; import type { RomIGDBMetadata } from './RomIGDBMetadata'; +import type { RomLaunchboxMetadata } from './RomLaunchboxMetadata'; import type { RomMetadataSchema } from './RomMetadataSchema'; import type { RomMobyMetadata } from './RomMobyMetadata'; import type { RomSSMetadata } from './RomSSMetadata'; @@ -16,6 +17,7 @@ export type SimpleRomSchema = { moby_id: (number | null); ss_id: (number | null); ra_id: (number | null); + launchbox_id: (number | null); platform_id: number; platform_slug: string; platform_fs_slug: string; @@ -37,6 +39,7 @@ export type SimpleRomSchema = { igdb_metadata: (RomIGDBMetadata | null); moby_metadata: (RomMobyMetadata | null); ss_metadata: (RomSSMetadata | null); + launchbox_metadata: (RomLaunchboxMetadata | null); path_cover_small: (string | null); path_cover_large: (string | null); url_cover: (string | null); @@ -44,6 +47,7 @@ export type SimpleRomSchema = { path_manual: (string | null); url_manual: (string | null); is_unidentified: boolean; + is_identified: boolean; revision: (string | null); regions: Array; languages: Array; diff --git a/frontend/src/components/Details/Title.vue b/frontend/src/components/Details/Title.vue index 5b191fc9d..c3897e043 100644 --- a/frontend/src/components/Details/Title.vue +++ b/frontend/src/components/Details/Title.vue @@ -88,7 +88,7 @@ const hasReleaseDate = Number(props.rom.metadatum.first_release_date) > 0; 0; {{ rom.ra_id }} +
+ + + + + {{ rom.launchbox_id }} + + {{ rom.launchbox_metadata?.community_rating }} + mdi-star + +
diff --git a/frontend/src/components/Gallery/AppBar/Platform/PlatformInfoDrawer.vue b/frontend/src/components/Gallery/AppBar/Platform/PlatformInfoDrawer.vue index ee2bc335d..368527078 100644 --- a/frontend/src/components/Gallery/AppBar/Platform/PlatformInfoDrawer.vue +++ b/frontend/src/components/Gallery/AppBar/Platform/PlatformInfoDrawer.vue @@ -292,11 +292,7 @@ watch( diff --git a/frontend/src/components/common/Game/Dialog/EditRom.vue b/frontend/src/components/common/Game/Dialog/EditRom.vue index 60a0eb6f3..c43289714 100644 --- a/frontend/src/components/common/Game/Dialog/EditRom.vue +++ b/frontend/src/components/common/Game/Dialog/EditRom.vue @@ -80,10 +80,6 @@ async function removeArtwork() { removeCover.value = true; } -const noMetadataMatch = computed(() => { - return !rom.value?.igdb_id && !rom.value?.moby_id && !rom.value?.ss_id; -}); - async function handleRomUpdate( options: { rom: UpdateRom; @@ -371,8 +367,8 @@ function closeDialog() { diff --git a/frontend/src/components/common/Game/RAvatar.vue b/frontend/src/components/common/Game/RAvatar.vue index 78102538c..5a2162587 100644 --- a/frontend/src/components/common/Game/RAvatar.vue +++ b/frontend/src/components/common/Game/RAvatar.vue @@ -8,7 +8,7 @@ const props = withDefaults(defineProps<{ rom: SimpleRom; size?: number }>(), { }); const fallbackCoverImage = computed(() => - props.rom.igdb_id || props.rom.moby_id + props.rom.is_identified ? getMissingCoverImage(props.rom.name || props.rom.fs_name) : getUnmatchedCoverImage(props.rom.name || props.rom.fs_name), ); diff --git a/frontend/src/components/common/Platform/ListItem.vue b/frontend/src/components/common/Platform/ListItem.vue index 08399b30a..66e61c9ae 100644 --- a/frontend/src/components/common/Platform/ListItem.vue +++ b/frontend/src/components/common/Platform/ListItem.vue @@ -32,7 +32,7 @@ withDefaults(defineProps<{ platform: Platform; rail?: boolean }>(), { open-delay="500" >