Commit Graph

234 Commits

Author SHA1 Message Date
Spinnich
01f0b1d2b5 feat(hashing): compute raw CHD hashes and route disc-data SHA1 to Hasheous
CHD files now follow the same hash logic as all other file types — CRC32,
MD5, and SHA1 are computed from raw container bytes. This allows
ScreenScraper to log KO entries for unrecognised CHD files, which it
could not do when only the disc-data SHA1 was being computed.

The CHD header SHA1 (disc-data SHA1) is separately extracted and stored
in a new chd_sha1_hash field on RomFile, with a migration adding the
column to rom_files. Hasheous receives only this disc-data SHA1 (no
CRC/MD5) since it indexes disc-based games by disc-data SHA1, not raw
file hashes.

The RAHasher multi-file path now passes the largest CHD directly instead
of a /* wildcard, which RAHasher cannot expand. Hash computations are
wrapped in asyncio.to_thread to avoid blocking the event loop during
large reads.

Hash-lookup metadata handlers (ScreenScraper, Hasheous, Playmatch) now
fall back to rom.files (stored DB hashes) when fs_rom files are not
rehashed, fixing hash-based matching for UNMATCHED and UPDATE scan types.

The Disc SHA-1 is displayed in the ROM detail view for both single-file
(FileInfo.vue) and multi-file (FileSelectItem.vue) CHD games.
2026-05-17 08:01:05 -04:00
Georges-Antoine Assi
c3c6829962 refactor(playmatch): use dict as single source of truth for provider tags
Replace the tuple+derived-dict pair with PLAYMATCH_TAG_TO_ATTR as the
canonical mapping. Rename enum members to UPPER_CASE, expand
PlaymatchRomMatch to cover all provider ids, and inline the fallback
match in place of the _empty_playmatch_rom_match helper.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-16 15:41:33 -04:00
Yukine
f307aeaca3 refactor(playmatch): move PLAYMATCH_SUPPORTED_SOURCES into playmatch_handler 2026-05-16 05:41:22 +02:00
Yukine
820595a160 refactor(playmatch): simplify comments 2026-05-16 05:21:22 +02:00
Yukine
563e1f4e76 feat(scan): lift IGDB gate from Playmatch and forward provider ids to fetch funcs 2026-05-16 05:17:37 +02:00
Georges-Antoine Assi
c6a2f56fad Merge pull request #3367 from rommapp/regional-provider-tags
Prefer ROM's own region tag for ScreenScraper and IGDB artwork
2026-05-13 11:19:53 -04:00
Georges-Antoine Assi
944514acc0 prefer rom's own region tag for ScreenScraper and IGDB artwork
When a ROM filename carries a region tag (e.g. (Europe)), use that
region first when picking artwork and localized titles, falling back to
the configured scan.priority.region. Previously the configured priority
was the only signal, so a US-first config would force US covers onto
European ROMs even when an EU asset was available.

Adds a shared name->provider-shortcode map and threads the rom through
the IGDB and SS lookup APIs so the rom-aware locale/region selection
can run for both providers.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-13 09:06:11 -04:00
Georges-Antoine Assi
8999b66574 Preserve local LaunchBox data on UPDATE scans and video extensions
UPDATE scans with a known launchbox_id were calling get_rom_by_id(),
which only returns remote data and bypassed get_rom()'s local-first
merge — so local-only fields like Notes were getting clobbered and
local media matching fidelity dropped. get_rom_by_id() now optionally
takes fs_name/platform_slug and merges the local entry when its
DatabaseID matches the requested id.

Also fixes populate_rom_specific_paths writing every video as
video.mp4 regardless of source extension; since store_media_file is a
byte copy, .mkv/.webm contents would be served as .mp4 and break MIME
sniffing.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 14:32:34 -04:00
Georges-Antoine Assi
fad2e5c77d Use correct LaunchBox MameFile schema
The sample_metadata.zip test fixture used invented tag names
(<Description>, FileName ending in .zip). Real LaunchBox Mame.xml
(see backend/tasks/fixtures/launchbox/mame.xml) uses <Name> as the
full title and keys MameFile entries by the stem (e.g. wrlok_l3),
no extension. Read Name instead of Description, and fall back to
the stem when the raw fs_name lookup misses.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-18 14:31:16 -04:00
Georges-Antoine Assi
8fc426b35c Import local LaunchBox videos
LaunchBox stores videos under /romm/launchbox/Videos/<Platform>/<Game>.<ext>
but the handler only extracted YouTube IDs; LAUNCHBOX_VIDEOS_DIR was
defined and unused. Add _get_video() to surface local videos as
launchbox-file:// URLs, thread a populate_rom_specific_paths() through
the scan pipeline to set video_path once the rom is known, and mirror
the SS/gamelist branch in the scan socket so store_media_file actually
copies the video into the rom's resource directory. Rom.path_video now
also reads from launchbox_metadata.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-18 12:13:42 -04:00
Georges-Antoine Assi
105ed84e43 feat: show TheGamesDB link on platform drawer when tgdb_id is set
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 19:04:51 -04:00
Georges-Antoine Assi
f94c1491e5 fix: respect SCAN_ARTWORK_PRIORITY for SGDB and align libretro search with SGDB pattern
SGDB's url_cover used to clobber whatever the artwork priority loop
picked, which meant user-set priorities (e.g. libretro > sgdb) and
manually uploaded covers were silently overridden. SGDB now only
replaces the current url_cover when it outranks every other source
that produced one under SCAN_ARTWORK_PRIORITY, and never over a
manual cover preserved on UPDATE/UNMATCHED scans. Default artwork
priority gains sgdb at the top so existing "SGDB wins" behavior is
preserved for default configs.

On the /search/roms endpoint, libretro is now an enrichment source
alongside SGDB instead of a primary match source: it decorates
entries resolved by IGDB/Moby/SS/Flashpoint/Launchbox with
libretro_id and libretro_url_cover, mirroring how SGDB works.
get_matched_roms_by_name is removed from the libretro handler since
nothing else calls it.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 11:52:44 -04:00
Georges-Antoine Assi
4928041593 manual cleanu 2026-04-12 11:04:12 -04:00
Georges-Antoine Assi
522df9d31a feat: add libretro thumbnails as an artwork source
Adds the libretro thumbnail repository as a first-class artwork source so
region-correct box art (PAL/Europe, Japan, etc.) can be matched directly
to ROM filenames, addressing rommapp/romm#3239.

Implementation follows the SGDB handler pattern (artwork-only, no game
metadata): MetadataSource enum entry, scan-time fetch wired into the
SCAN_ARTWORK_PRIORITY loop, /search/roms integration, MatchRom dialog
chip + cover selection, and a heartbeat flag.

Matching is exact case-insensitive against the directory listing first
(so a ROM named "(Europe)" lands on the (Europe) artwork), with a
JaroWinkler fuzzy fallback at 0.8 that strips parenthetical tags from
both sides. Listings are cached in Redis with a 24h TTL.

`libretro_id` is persisted on the Rom model as the SHA1 hex of the
matched libretro filename — stable across scans, distinct per region,
indexed for lookup. Migration 0077 adds the column.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 22:57:20 -04:00
Georges-Antoine Assi
6db9d45928 actually fix 2026-04-07 22:53:44 -04:00
copilot-swe-agent[bot]
24fe5b941f refactor: move get_pico8_cover_url to FSRomsHandler, use validate_path for safe path construction
Co-authored-by: gantoine <3247106+gantoine@users.noreply.github.com>
2026-03-11 22:17:22 +00:00
copilot-swe-agent[bot]
2958e6f12b feat: use PICO-8 built-in cover art from .p8.png cartridge files
Co-authored-by: gantoine <3247106+gantoine@users.noreply.github.com>
2026-03-11 02:35:18 +00:00
Georges-Antoine Assi
eda88b70d1 get claude to refactor launchbox_handler 2026-03-07 16:02:39 -05:00
Georges-Antoine Assi
6de46eb067 Merge branch 'master' into launchbox-handler 2026-03-07 11:31:03 -05:00
Georges-Antoine Assi
77823c168d [AIKIDO-13126604] Stream file when building file hash 2026-02-16 13:51:20 -05:00
nendo
bf8cb92e93 refactor(assets): move content hash functions to assets_handler
Move compute_file_hash, compute_zip_hash, and compute_content_hash from
scan_handler.py to filesystem/assets_handler.py as standalone module-level
functions. This follows the existing pattern for utility functions in
filesystem handlers.
2026-02-03 20:07:18 +09:00
nendo
a236123e4f feat(saves): add slot-based save sync with content hash deduplication
- Add device registration and save synchronization
- Implement slot-based save organization with datetime tagging
- Add conflict detection for multi-device sync scenarios
- Add content hash computation for save deduplication
- Support ZIP inner-file hashing for consistent deduplication
- Add confirm_download endpoint for sync state management
- Add overwrite parameter to bypass conflict checks
2026-01-31 21:57:22 +09:00
Georges-Antoine Assi
f432847793 fixes after merge 2026-01-28 15:01:37 -05:00
Georges-Antoine Assi
2a1583e504 Merge branch 'master' into launchbox-handler 2026-01-28 15:01:01 -05:00
Gravel Freeman
732cc2a530 add support for importing metadata from a local launchbox installation 2026-01-19 13:12:27 -05:00
Georges-Antoine Assi
ff9b29d90e [HOTFIX] Remove files from model_dump in scan 2026-01-17 22:31:48 -05:00
Georges-Antoine Assi
76d445ccd9 [ROMM-2722] Fix matching special chars in ssfr 2025-12-07 21:21:57 -05:00
Georges-Antoine Assi
8fe435e0b4 Cache parsed gamelist.xml files on each scan 2025-11-19 18:00:12 -05:00
Georges-Antoine Assi
f8b0ae63a1 fix scanning multi file games with ssfr 2025-10-31 10:50:51 -04:00
Georges-Antoine Assi
0424e4450f implement hash lookup for ssfr 2025-10-30 16:00:47 -04:00
Georges-Antoine Assi
c1ac9a2133 fix screenshots dissapearing on scan 2025-10-28 11:00:45 -04:00
Georges-Antoine Assi
b1b982eaae reorder scan functions a bit 2025-10-28 10:21:56 -04:00
Georges-Antoine Assi
417aaf4e29 fuix props reset 2025-10-28 09:30:44 -04:00
Georges-Antoine Assi
a2cfd571c5 fix filesize reset on partial scan 2025-10-28 08:56:45 -04:00
Georges-Antoine Assi
f30f0bfd75 Smarter detection of whether to scan roms 2025-10-26 13:21:56 -04:00
Georges-Antoine Assi
d928c9705f fix media storage for gamelistxml 2025-10-24 19:06:45 -04:00
Georges-Antoine Assi
463bb27ea9 Add config to store media on disk 2025-10-24 16:04:54 -04:00
Georges-Antoine Assi
a7c4cd75f5 update scans should fetch by ID 2025-10-23 21:51:09 -04:00
Georges-Antoine Assi
9fa15d20f0 totally refactor scan types 2025-10-23 16:57:40 -04:00
Georges-Antoine Assi
3575783769 Merge branch 'master' into romm-821 2025-10-21 21:46:23 -04:00
Georges-Antoine Assi
b689e3bde1 [ROMM-2531] Allow scanning without metadata providers 2025-10-19 12:37:18 -04:00
Georges-Antoine Assi
9269e36608 populate scan results with edge 2025-10-17 15:32:38 -04:00
Georges-Antoine Assi
3cfc52234a start work on gamelist.xml extraction 2025-10-16 23:16:39 -04:00
Georges-Antoine Assi
896b9edd17 Show indicator if platform not identified 2025-09-30 21:22:07 -04:00
Georges-Antoine Assi
b5776be475 Split rom.multi into more specific fields 2025-09-25 18:48:27 -04:00
Georges-Antoine Assi
e473cbe698 Move url_cover checks to scan_handler 2025-09-24 09:52:49 -04:00
Georges-Antoine Assi
1bd7b69b2c set url_cover to fake tld 2025-09-23 22:29:21 -04:00
Georges-Antoine Assi
c0716c05af fix type for test 2025-09-23 18:38:28 -04:00
Georges-Antoine Assi
3a3bffe699 progressive scan steps for each game 2025-09-23 10:23:57 -04:00
Georges-Antoine Assi
6eed0b6c7f Set platform metadata slugs on models in DB 2025-09-22 21:48:45 -04:00