manual cleanu

This commit is contained in:
Georges-Antoine Assi
2026-04-12 11:04:12 -04:00
parent b3c79ab6ff
commit 4928041593
19 changed files with 231 additions and 129 deletions

View File

@@ -29,8 +29,17 @@ def upgrade() -> None:
if_not_exists=True,
)
with op.batch_alter_table("platforms", schema=None) as batch_op:
batch_op.add_column(
sa.Column("libretro_slug", sa.String(length=100), nullable=True),
if_not_exists=True,
)
def downgrade() -> None:
with op.batch_alter_table("roms", schema=None) as batch_op:
batch_op.drop_index("idx_roms_libretro_id", if_exists=True)
batch_op.drop_column("libretro_id", if_exists=True)
with op.batch_alter_table("platforms", schema=None) as batch_op:
batch_op.drop_column("libretro_slug", if_exists=True)

View File

@@ -17,6 +17,7 @@ class PlatformSchema(BaseModel):
igdb_slug: str | None
moby_slug: str | None
hltb_slug: str | None
libretro_slug: str | None
custom_name: str | None = None
igdb_id: int | None = None
sgdb_id: int | None = None

View File

@@ -1,98 +1,25 @@
import hashlib
import os
import re
from sys import platform
from typing import Final, NotRequired, TypedDict
from adapters.services.libretro_thumbnails import (
LIBRETRO_THUMBNAIL_ROOT,
LibretroThumbnailsService,
)
from adapters.services.libretro_thumbnails import LibretroThumbnailsService
from adapters.services.libretro_thumbnails_types import LibretroArtType
from handler.metadata.igdb_handler import IGDB_PLATFORM_LIST
from logger.logger import log
from .base_handler import MetadataHandler, UniversalPlatformSlug
# Mapping of RomM UniversalPlatformSlug values to libretro thumbnail
# directory names (https://thumbnails.libretro.com/).
LIBRETRO_PLATFORM_LIST: Final[dict[UniversalPlatformSlug, str]] = {
UniversalPlatformSlug.ADVENTURE_VISION: "Entex - Adventure Vision",
UniversalPlatformSlug.AMIGA: "Commodore - Amiga",
UniversalPlatformSlug.AMIGA_CD32: "Commodore - Amiga",
UniversalPlatformSlug.ACPC: "Amstrad - CPC",
UniversalPlatformSlug.ATARI2600: "Atari - 2600",
UniversalPlatformSlug.ATARI5200: "Atari - 5200",
UniversalPlatformSlug.ATARI7800: "Atari - 7800",
UniversalPlatformSlug.ATARI_ST: "Atari - ST",
UniversalPlatformSlug.JAGUAR: "Atari - Jaguar",
UniversalPlatformSlug.LYNX: "Atari - Lynx",
UniversalPlatformSlug.WONDERSWAN: "Bandai - WonderSwan",
UniversalPlatformSlug.WONDERSWAN_COLOR: "Bandai - WonderSwan Color",
UniversalPlatformSlug.COLECOVISION: "Coleco - ColecoVision",
UniversalPlatformSlug.C64: "Commodore - 64",
UniversalPlatformSlug.VIC_20: "Commodore - VIC-20",
UniversalPlatformSlug.DOS: "DOS",
UniversalPlatformSlug.FAIRCHILD_CHANNEL_F: "Fairchild - Channel F",
UniversalPlatformSlug.VECTREX: "GCE - Vectrex",
UniversalPlatformSlug.ODYSSEY_2: "Magnavox - Odyssey2",
UniversalPlatformSlug.INTELLIVISION: "Mattel - Intellivision",
UniversalPlatformSlug.MSX: "Microsoft - MSX",
UniversalPlatformSlug.MSX2: "Microsoft - MSX2",
UniversalPlatformSlug.XBOX: "Microsoft - XBOX",
UniversalPlatformSlug.PC_8800_SERIES: "NEC - PC Engine - TurboGrafx 16",
UniversalPlatformSlug.PC_FX: "NEC - PC-FX",
UniversalPlatformSlug.PC_9800_SERIES: "NEC - PC-98",
UniversalPlatformSlug.SUPERGRAFX: "NEC - PC Engine SuperGrafx",
UniversalPlatformSlug.TG16: "NEC - PC Engine - TurboGrafx 16",
UniversalPlatformSlug.TURBOGRAFX_CD: "NEC - PC Engine CD - TurboGrafx-CD",
UniversalPlatformSlug.FDS: "Nintendo - Family Computer Disk System",
UniversalPlatformSlug.GB: "Nintendo - Game Boy",
UniversalPlatformSlug.GBA: "Nintendo - Game Boy Advance",
UniversalPlatformSlug.GBC: "Nintendo - Game Boy Color",
UniversalPlatformSlug.NGC: "Nintendo - GameCube",
UniversalPlatformSlug.N64: "Nintendo - Nintendo 64",
UniversalPlatformSlug.N64DD: "Nintendo - Nintendo 64DD",
UniversalPlatformSlug.N3DS: "Nintendo - Nintendo 3DS",
UniversalPlatformSlug.NDS: "Nintendo - Nintendo DS",
UniversalPlatformSlug.NES: "Nintendo - Nintendo Entertainment System",
UniversalPlatformSlug.FAMICOM: "Nintendo - Nintendo Entertainment System",
UniversalPlatformSlug.POKEMON_MINI: "Nintendo - Pokemon Mini",
UniversalPlatformSlug.SATELLAVIEW: "Nintendo - Satellaview",
UniversalPlatformSlug.SUFAMI_TURBO: "Nintendo - Sufami Turbo",
UniversalPlatformSlug.SNES: "Nintendo - Super Nintendo Entertainment System",
UniversalPlatformSlug.SFAM: "Nintendo - Super Nintendo Entertainment System",
UniversalPlatformSlug.VIRTUALBOY: "Nintendo - Virtual Boy",
UniversalPlatformSlug.WII: "Nintendo - Wii",
UniversalPlatformSlug.WIIU: "Nintendo - Wii U",
UniversalPlatformSlug.SCUMMVM: "ScummVM",
UniversalPlatformSlug.SEGA32: "Sega - 32X",
UniversalPlatformSlug.DC: "Sega - Dreamcast",
UniversalPlatformSlug.GAMEGEAR: "Sega - Game Gear",
UniversalPlatformSlug.GENESIS: "Sega - Mega Drive - Genesis",
UniversalPlatformSlug.SEGACD: "Sega - Mega-CD - Sega CD",
UniversalPlatformSlug.SMS: "Sega - Master System - Mark III",
UniversalPlatformSlug.SG1000: "Sega - SG-1000",
UniversalPlatformSlug.SATURN: "Sega - Saturn",
UniversalPlatformSlug.X1: "Sharp - X1",
UniversalPlatformSlug.SHARP_X68000: "Sharp - X68000",
UniversalPlatformSlug.ZX81: "Sinclair - ZX 81",
UniversalPlatformSlug.ZXS: "Sinclair - ZX Spectrum",
UniversalPlatformSlug.NEOGEOAES: "SNK - Neo Geo",
UniversalPlatformSlug.NEOGEOMVS: "SNK - Neo Geo",
UniversalPlatformSlug.NEO_GEO_CD: "SNK - Neo Geo CD",
UniversalPlatformSlug.NEO_GEO_POCKET: "SNK - Neo Geo Pocket",
UniversalPlatformSlug.NEO_GEO_POCKET_COLOR: "SNK - Neo Geo Pocket Color",
UniversalPlatformSlug.PSX: "Sony - PlayStation",
UniversalPlatformSlug.PS2: "Sony - PlayStation 2",
UniversalPlatformSlug.PSP: "Sony - PlayStation Portable",
UniversalPlatformSlug.TIC_80: "TIC-80",
UniversalPlatformSlug.TOMY_TUTOR: "Tomy - Tutor",
UniversalPlatformSlug.SUPERVISION: "Watara - Supervision",
}
from .base_handler import MetadataHandler
from .base_handler import UniversalPlatformSlug as UPS
_PAREN_TAG_PATTERN = re.compile(r"\([^)]*\)")
class LibretroPlatform(TypedDict):
slug: str
libretro_slug: str | None
class LibretroRom(TypedDict):
libretro_id: str | None
url_cover: NotRequired[str]
@@ -131,7 +58,6 @@ class LibretroHandler(MetadataHandler):
@classmethod
def is_enabled(cls) -> bool:
# Public server, no API key required. Always enabled.
return True
async def heartbeat(self) -> bool:
@@ -141,12 +67,13 @@ class LibretroHandler(MetadataHandler):
log.error("Error checking libretro thumbnails: %s", exc)
return False
def _resolve_system(self, platform_slug: str) -> str | None:
try:
ups = UniversalPlatformSlug(platform_slug)
except ValueError:
return None
return LIBRETRO_PLATFORM_LIST.get(ups)
def get_platform(self, slug: str) -> LibretroPlatform:
if slug in LIBRETRO_PLATFORM_LIST:
libretro_slug = LIBRETRO_PLATFORM_LIST[UPS(slug)]
return LibretroPlatform(slug=slug, libretro_slug=libretro_slug)
return LibretroPlatform(slug=slug, libretro_slug=None)
def _find_exact_match(self, target: str, listing: list[str]) -> str | None:
"""Case-insensitive exact match on filename (extension stripped)."""
@@ -197,11 +124,13 @@ class LibretroHandler(MetadataHandler):
omitted because libretro artwork filenames are not proper game names —
letting them overwrite a real name from IGDB/Moby would be wrong.
"""
system_name = self._resolve_system(platform_slug)
if not system_name:
platform = self.get_platform(platform_slug)
if not platform or not platform["libretro_slug"]:
return LibretroRom(libretro_id=None)
listing = await self.service.fetch_listing(system_name, LibretroArtType.BOX_ART)
listing = await self.service.fetch_listing(
platform["libretro_slug"], LibretroArtType.BOX_ART
)
if not listing:
return LibretroRom(libretro_id=None)
@@ -210,7 +139,7 @@ class LibretroHandler(MetadataHandler):
return LibretroRom(libretro_id=None)
url = LibretroThumbnailsService.build_art_url(
system_name, LibretroArtType.BOX_ART, matched
platform["libretro_slug"], LibretroArtType.BOX_ART, matched
)
return LibretroRom(
libretro_id=libretro_id_for(matched),
@@ -226,11 +155,13 @@ class LibretroHandler(MetadataHandler):
tag-stripped title matches the search term on either an exact or
fuzzy basis.
"""
system_name = self._resolve_system(platform_slug)
if not system_name:
platform = self.get_platform(platform_slug)
if not platform or not platform["libretro_slug"]:
return []
listing = await self.service.fetch_listing(system_name, LibretroArtType.BOX_ART)
listing = await self.service.fetch_listing(
platform["libretro_slug"], LibretroArtType.BOX_ART
)
if not listing:
return []
@@ -260,7 +191,7 @@ class LibretroHandler(MetadataHandler):
LibretroRom(
libretro_id=libretro_id_for(filename),
url_cover=LibretroThumbnailsService.build_art_url(
system_name, LibretroArtType.BOX_ART, filename
platform["libretro_slug"], LibretroArtType.BOX_ART, filename
),
name=stripped,
)
@@ -276,9 +207,85 @@ class LibretroHandler(MetadataHandler):
LibretroRom(
libretro_id=libretro_id_for(fuzzy),
url_cover=LibretroThumbnailsService.build_art_url(
system_name, LibretroArtType.BOX_ART, fuzzy
platform["libretro_slug"], LibretroArtType.BOX_ART, fuzzy
),
name=_strip_paren_tags(_remove_file_extension(fuzzy)),
)
)
return matches[:limit]
LIBRETRO_PLATFORM_LIST: Final[dict[UPS, str]] = {
UPS.ADVENTURE_VISION: "Entex - Adventure Vision",
UPS.AMIGA: "Commodore - Amiga",
UPS.AMIGA_CD32: "Commodore - Amiga",
UPS.ACPC: "Amstrad - CPC",
UPS.ATARI2600: "Atari - 2600",
UPS.ATARI5200: "Atari - 5200",
UPS.ATARI7800: "Atari - 7800",
UPS.ATARI_ST: "Atari - ST",
UPS.JAGUAR: "Atari - Jaguar",
UPS.LYNX: "Atari - Lynx",
UPS.WONDERSWAN: "Bandai - WonderSwan",
UPS.WONDERSWAN_COLOR: "Bandai - WonderSwan Color",
UPS.COLECOVISION: "Coleco - ColecoVision",
UPS.C64: "Commodore - 64",
UPS.VIC_20: "Commodore - VIC-20",
UPS.DOS: "DOS",
UPS.FAIRCHILD_CHANNEL_F: "Fairchild - Channel F",
UPS.VECTREX: "GCE - Vectrex",
UPS.ODYSSEY_2: "Magnavox - Odyssey2",
UPS.INTELLIVISION: "Mattel - Intellivision",
UPS.MSX: "Microsoft - MSX",
UPS.MSX2: "Microsoft - MSX2",
UPS.XBOX: "Microsoft - XBOX",
UPS.PC_8800_SERIES: "NEC - PC Engine - TurboGrafx 16",
UPS.PC_FX: "NEC - PC-FX",
UPS.PC_9800_SERIES: "NEC - PC-98",
UPS.SUPERGRAFX: "NEC - PC Engine SuperGrafx",
UPS.TG16: "NEC - PC Engine - TurboGrafx 16",
UPS.TURBOGRAFX_CD: "NEC - PC Engine CD - TurboGrafx-CD",
UPS.FDS: "Nintendo - Family Computer Disk System",
UPS.GB: "Nintendo - Game Boy",
UPS.GBA: "Nintendo - Game Boy Advance",
UPS.GBC: "Nintendo - Game Boy Color",
UPS.NGC: "Nintendo - GameCube",
UPS.N64: "Nintendo - Nintendo 64",
UPS.N64DD: "Nintendo - Nintendo 64DD",
UPS.N3DS: "Nintendo - Nintendo 3DS",
UPS.NDS: "Nintendo - Nintendo DS",
UPS.NES: "Nintendo - Nintendo Entertainment System",
UPS.FAMICOM: "Nintendo - Nintendo Entertainment System",
UPS.POKEMON_MINI: "Nintendo - Pokemon Mini",
UPS.SATELLAVIEW: "Nintendo - Satellaview",
UPS.SUFAMI_TURBO: "Nintendo - Sufami Turbo",
UPS.SNES: "Nintendo - Super Nintendo Entertainment System",
UPS.SFAM: "Nintendo - Super Nintendo Entertainment System",
UPS.VIRTUALBOY: "Nintendo - Virtual Boy",
UPS.WII: "Nintendo - Wii",
UPS.WIIU: "Nintendo - Wii U",
UPS.SCUMMVM: "ScummVM",
UPS.SEGA32: "Sega - 32X",
UPS.DC: "Sega - Dreamcast",
UPS.GAMEGEAR: "Sega - Game Gear",
UPS.GENESIS: "Sega - Mega Drive - Genesis",
UPS.SEGACD: "Sega - Mega-CD - Sega CD",
UPS.SMS: "Sega - Master System - Mark III",
UPS.SG1000: "Sega - SG-1000",
UPS.SATURN: "Sega - Saturn",
UPS.X1: "Sharp - X1",
UPS.SHARP_X68000: "Sharp - X68000",
UPS.ZX81: "Sinclair - ZX 81",
UPS.ZXS: "Sinclair - ZX Spectrum",
UPS.NEOGEOAES: "SNK - Neo Geo",
UPS.NEOGEOMVS: "SNK - Neo Geo",
UPS.NEO_GEO_CD: "SNK - Neo Geo CD",
UPS.NEO_GEO_POCKET: "SNK - Neo Geo Pocket",
UPS.NEO_GEO_POCKET_COLOR: "SNK - Neo Geo Pocket Color",
UPS.PSX: "Sony - PlayStation",
UPS.PS2: "Sony - PlayStation 2",
UPS.PSP: "Sony - PlayStation Portable",
UPS.TIC_80: "TIC-80",
UPS.TOMY_TUTOR: "Tomy - Tutor",
UPS.SUPERVISION: "Watara - Supervision",
}

View File

@@ -182,10 +182,12 @@ async def scan_platform(
tgdb_platform = meta_tgdb_handler.get_platform(platform_attrs["slug"])
flashpoint_platform = meta_flashpoint_handler.get_platform(platform_attrs["slug"])
hltb_platform = meta_hltb_handler.get_platform(platform_attrs["slug"])
libretro_platform = meta_libretro_handler.get_platform(platform_attrs["slug"])
platform_attrs["name"] = platform_attrs["slug"].replace("-", " ").title()
platform_attrs.update(
{
**libretro_platform,
**hltb_platform,
**flashpoint_platform,
**tgdb_platform,
@@ -228,6 +230,7 @@ async def scan_platform(
or tgdb_platform["tgdb_id"]
or flashpoint_platform["flashpoint_id"]
or hltb_platform["hltb_slug"]
or libretro_platform["libretro_slug"]
):
log.info(
f"Folder {hl(platform_attrs['slug'])}[{hl(fs_slug, color=LIGHTYELLOW)}] identified as {hl(platform_attrs['name'], color=BLUE)} {emoji.EMOJI_VIDEO_GAME}",

View File

@@ -31,6 +31,7 @@ class Platform(BaseModel):
igdb_slug: Mapped[str | None] = mapped_column(String(length=100), default=None)
moby_slug: Mapped[str | None] = mapped_column(String(length=100), default=None)
hltb_slug: Mapped[str | None] = mapped_column(String(length=100), default=None)
libretro_slug: Mapped[str | None] = mapped_column(String(length=100), default=None)
slug: Mapped[str] = mapped_column(String(length=100))
fs_slug: Mapped[str] = mapped_column(String(length=100))
name: Mapped[str] = mapped_column(String(length=400))

View File

@@ -9,6 +9,7 @@ from handler.metadata import (
meta_hltb_handler,
meta_igdb_handler,
meta_launchbox_handler,
meta_libretro_handler,
meta_moby_handler,
meta_ra_handler,
meta_sgdb_handler,
@@ -51,6 +52,7 @@ class ScanLibraryTask(PeriodicTask):
MetadataSource.FLASHPOINT: meta_flashpoint_handler.is_enabled(),
MetadataSource.HLTB: meta_hltb_handler.is_enabled(),
MetadataSource.TGDB: meta_tgdb_handler.is_enabled(),
MetadataSource.LIBRETRO: meta_libretro_handler.is_enabled(),
}
metadata_sources = [source for source, flag in source_mapping.items() if flag]

View File

@@ -7,6 +7,7 @@ from handler.metadata.hasheous_handler import HasheousHandler
from handler.metadata.hltb_handler import HLTBHandler
from handler.metadata.igdb_handler import IGDBHandler
from handler.metadata.launchbox_handler.handler import LaunchboxHandler
from handler.metadata.libretro_handler import LibretroHandler
from handler.metadata.moby_handler import MobyGamesHandler
from handler.metadata.ra_handler import RAHandler
from handler.metadata.sgdb_handler import SGDBBaseHandler
@@ -38,6 +39,7 @@ class TestScanLibraryTask:
mocker.patch.object(FlashpointHandler, "is_enabled", return_value=False)
mocker.patch.object(HLTBHandler, "is_enabled", return_value=False)
mocker.patch.object(TGDBHandler, "is_enabled", return_value=False)
mocker.patch.object(LibretroHandler, "is_enabled", return_value=False)
mocker.patch("tasks.scheduled.scan_library.ENABLE_SCHEDULED_RESCAN", True)
scan_result = MagicMock()

View File

@@ -7,6 +7,7 @@ from handler.metadata import (
meta_hltb_handler,
meta_igdb_handler,
meta_launchbox_handler,
meta_libretro_handler,
meta_moby_handler,
meta_ra_handler,
meta_ss_handler,
@@ -25,6 +26,7 @@ class SupportedPlatform(TypedDict):
ra_id: int | None
flashpoint_id: int | None
hltb_slug: str | None
libretro_slug: str | None
if __name__ == "__main__":
@@ -41,6 +43,7 @@ if __name__ == "__main__":
ra_platform = meta_ra_handler.get_platform(slug_lower)
flashpoint_platform = meta_flashpoint_handler.get_platform(slug_lower)
hltb_platform = meta_hltb_handler.get_platform(slug_lower)
libretro_platform = meta_libretro_handler.get_platform(slug_lower)
supported_platforms[slug_lower] = {
"name": igdb_platform.get("name", None)
@@ -61,6 +64,7 @@ if __name__ == "__main__":
"ra_id": ra_platform["ra_id"],
"flashpoint_id": flashpoint_platform["flashpoint_id"],
"hltb_slug": hltb_platform.get("hltb_slug", None),
"libretro_slug": libretro_platform.get("libretro_slug", None),
}
# Sort platforms by name field
@@ -115,5 +119,10 @@ if __name__ == "__main__":
if platform["hltb_slug"]
else ""
),
(
f'<a href="https://thumbnails.libretro.com/{platform["libretro_slug"]}" target="_blank" rel="noopener noreferrer"><img alt="libretro logo" src="../../resources/metadata_providers/libretro.png" height="24px" width="24px"></a>'
if platform["libretro_slug"]
else ""
),
" |",
)

View File

@@ -28,6 +28,7 @@ from handler.metadata import (
meta_hltb_handler,
meta_igdb_handler,
meta_launchbox_handler,
meta_libretro_handler,
meta_moby_handler,
meta_ra_handler,
meta_sgdb_handler,
@@ -185,6 +186,7 @@ def process_changes(changes: Sequence[Change]) -> None:
MetadataSource.FLASHPOINT: meta_flashpoint_handler.is_enabled(),
MetadataSource.HLTB: meta_hltb_handler.is_enabled(),
MetadataSource.TGDB: meta_tgdb_handler.is_enabled(),
MetadataSource.LIBRETRO: meta_libretro_handler.is_enabled(),
}
metadata_sources = [source for source, flag in source_mapping.items() if flag]
if not metadata_sources:

View File

@@ -82,34 +82,35 @@
# priority:
# # Below are the default priority values used
# metadata: # Top-level metadata source priority
# - "igdb" # IGDB (highest priority)
# - "moby" # MobyGames
# - "ss" # Screenscraper
# - "ra" # RetroAchievements
# - "launchbox" # Launchbox
# - "gamelist" # ES-DE gamelist.xml
# - "hasheous" # Hasheous
# - "flashpoint" # Flashpoint Project
# - "hltb" # HowLongToBeat (lowest priority)
# - igdb # IGDB (highest priority)
# - moby # MobyGames
# - ss # Screenscraper
# - ra # RetroAchievements
# - launchbox # Launchbox
# - gamelist # ES-DE gamelist.xml
# - hasheous # Hasheous
# - flashpoint # Flashpoint Project
# - hltb # HowLongToBeat (lowest priority)
# artwork: # Cover art and screenshots
# - "igdb" # IGDB
# - "moby" # MobyGames
# - "ss" # Screenscraper
# - "ra" # RetroAchievements
# - "launchbox" # Launchbox
# - "gamelist" # ES-DE gamelist.xml
# - "hasheous" # Hasheous
# - "flashpoint" # Flashpoint Project
# - "hltb" # HowLongToBeat
# - igdb # IGDB
# - moby # MobyGames
# - ss # Screenscraper
# - ra # RetroAchievements
# - launchbox # Launchbox
# - libretro # Libretro
# - gamelist # ES-DE gamelist.xml
# - hasheous # Hasheous
# - flashpoint # Flashpoint Project
# - hltb # HowLongToBeat
# region: # Used by IGDB and ScreenScraper for regional variants
# - "us"
# - "wor"
# - "ss"
# - "eu"
# - "jp"
# - us
# - wor
# - ss
# - eu
# - jp
# language: # Used by ScreenScraper for descriptions
# - "en"
# - "fr"
# - en
# - fr
# # Media assets to download
# # Only used by Screenscraper and ES-DE gamelist.xml
# media:

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View File

@@ -12,6 +12,7 @@ export type PlatformSchema = {
igdb_slug: (string | null);
moby_slug: (string | null);
hltb_slug: (string | null);
libretro_slug: (string | null);
custom_name?: (string | null);
igdb_id?: (number | null);
sgdb_id?: (number | null);

View File

@@ -113,6 +113,7 @@ const coverImageSource = computed(() => {
if (hostname === "hasheous.org") return "Hasheous";
if (hostname === "infinity.unstable.life") return "Flashpoint";
if (hostname === "howlongtobeat.com") return "HowLongToBeat";
if (hostname === "thumbnails.libretro.com") return "Libretro";
return null;
} catch {

View File

@@ -24,6 +24,9 @@ const releaseDate = new Date(
const platformsStore = storePlatforms();
const { allPlatforms } = storeToRefs(platformsStore);
const platform = computed(() => {
return allPlatforms.value.find((p) => p.id === props.rom.platform_id);
});
const hashMatches = computed(() => {
return [
@@ -79,10 +82,7 @@ const hashMatches = computed(() => {
:to="{ name: ROUTES.PLATFORM, params: { platform: rom.platform_id } }"
>
<MissingFromFSIcon
v-if="
allPlatforms.find((p) => p.id === rom.platform_id)
?.missing_from_fs
"
v-if="platform?.missing_from_fs"
class="mr-2"
text="Missing platform from filesystem"
/>
@@ -328,6 +328,19 @@ const hashMatches = computed(() => {
<span>{{ rom.sgdb_id }}</span>
</v-chip>
</a>
<a
v-if="platform && rom.libretro_id"
style="text-decoration: none; color: inherit"
:href="`https://thumbnails.libretro.com/${platform.libretro_slug}/Named_Boxarts/${rom.fs_name_no_ext}.png`"
target="_blank"
class="mr-1"
>
<v-chip class="px-0 mt-1" size="small" title="Libretro match">
<v-avatar variant="text" size="30" rounded="0">
<v-img src="/assets/scrappers/libretro.png" />
</v-avatar>
</v-chip>
</a>
</v-col>
</v-row>
<v-row

View File

@@ -524,6 +524,16 @@ watch(
<v-img src="/assets/scrappers/hltb.png" />
</v-avatar>
</v-chip>
<v-chip
v-if="currentPlatform.libretro_slug"
class="px-0 ml-1 mt-1"
size="small"
title="Libretro"
>
<v-avatar variant="text" class="bg-surface" size="30" rounded="0">
<v-img src="/assets/scrappers/libretro.png" />
</v-avatar>
</v-chip>
</v-col>
</v-row>
<v-row v-else class="mt-2 text-center" no-gutters>

View File

@@ -179,6 +179,16 @@ const { t } = useI18n();
<v-img src="/assets/scrappers/esde.png" />
</v-avatar>
</v-chip>
<v-chip
v-if="rom.libretro_id"
class="pa-1 bg-surface"
size="small"
title="Libretro match"
>
<v-avatar variant="text" size="18" rounded>
<v-img src="/assets/scrappers/libretro.png" />
</v-avatar>
</v-chip>
</template>
</template>
</RomListItem>

View File

@@ -299,6 +299,16 @@ function updateOptions({ sortBy }: { sortBy: SortBy }) {
<v-img src="/assets/scrappers/esde.png" />
</v-avatar>
</v-chip>
<v-chip
v-if="item.libretro_id"
class="mr-1 pa-0 item-chip"
size="x-small"
title="Libretro match"
>
<v-avatar variant="text" size="20" rounded>
<v-img src="/assets/scrappers/libretro.png" />
</v-avatar>
</v-chip>
<v-chip
v-if="item.siblings.length > 0 && showSiblings"
class="translucent mr-1 px-1 item-chip"

View File

@@ -758,6 +758,16 @@ onMounted(async () => {
>
<v-img src="/assets/scrappers/hltb.png" />
</v-avatar>
<v-avatar
v-if="item.raw.libretro_slug"
class="bg-surface"
variant="text"
size="25"
rounded
>
<v-img src="/assets/scrappers/libretro.png" />
</v-avatar>
</v-col>
</v-row>
<v-row v-else class="text-center" no-gutters>

View File

@@ -302,13 +302,23 @@ async function stopScan() {
<v-avatar
v-if="item.raw.hltb_slug"
class="bg-surface"
class="bg-surface mr-1"
variant="text"
size="25"
rounded
>
<v-img src="/assets/scrappers/hltb.png" />
</v-avatar>
<v-avatar
v-if="item.raw.libretro_slug"
class="bg-surface"
variant="text"
size="25"
rounded
>
<v-img src="/assets/scrappers/libretro.png" />
</v-avatar>
</v-col>
</v-row>
<v-row v-else class="text-center" no-gutters>