Repository navigation
Fix scan destroying/mistitling pre-arranged libraries; add bulk metadata refresh - #11
Merged
Merged
Conversation
detectInputs only excluded folders it could match against a Game row in the DB. A folder with gameledger's own structure (artwork/ + data/*.zip) but no DB row — e.g. after a reinstall with a fresh database, or a library copied/hand-arranged in the same naming scheme — was queued as raw scan input. The pipeline would then re-match it, compress the folder into a zip nested inside itself, and delete the whole folder as the "source" on success, destroying an already-complete game. Structured folders are now recognized on sight and never queued as raw input, regardless of what the database knows. Orphaned ones (no matching Game row) are adopted instead: the IGDB ID is recovered from the folder/zip name via a new reverse-parser for the naming scheme, existing artwork/ archive paths are reused as-is, and metadata is refreshed from IGDB on a best-effort basis.
Scan progress streamed live per-job over the WebSocket, but nothing marked the run as a whole done — games (or adopted folders) just appeared with no feedback, especially noticeable off the Settings page or for scheduled scans. The scanner now broadcasts one 'scan' summary event when scanAll() finishes (games added, folders adopted, unmatched, failed, or cancelled). The frontend picks it up via a small global toast store/host mounted at the app root, so the notification shows up regardless of which page is open.
adoptFolder's fallback (when IGDB can't be reached at adopt time - e.g. credentials not yet re-entered on a reinstall) used cleanSourceName() on the whole folder name, which only strips dots/underscores. For a folder like "Clair Obscur Expedition 33 - 2025 [305152]" that left the year and IGDB ID baked into the title verbatim instead of just "Clair Obscur Expedition 33". naming.js now exposes parseFolderName(), extending the existing IGDB-ID reverse-parser to also recover the title and release year encoded by the active naming scheme. adoptFolder uses those as the fallback name/year when IGDB metadata isn't available, instead of the raw scheme-shaped string. extractIgdbId() is now a thin wrapper over parseFolderName().
Adopted/scanned games can end up with wrong-but-present or blank metadata fields (e.g. the folder-name-as-title bug from before this fix) with no way to correct them in bulk short of editing each one by hand. New POST /api/games/refresh-metadata (services/metadataRefresh.js), with two modes matching the issue: "all" unconditionally re-fetches metadata and wipes+redownloads artwork for every game (fixes wrong-but-present fields); "missing" only fills in blank fields (summary/genres/platforms/rating/ releaseYear/cover), leaving everything else untouched. Neither mode moves or renames gamePath/archivePath - per the naming-system invariant, a metadata correction is a cheap update, not a relocation. Fire-and-forget like /scan, with progress and a completion summary broadcast over the WebSocket. Manage Games gets two buttons for the two modes, a "Missing info" badge per game, and a live progress indicator; the completion summary surfaces via the existing global toast host and reloads the table.
Not every change needs a comment, and comments shouldn't tie themselves to a specific tracker issue -- that context rots once the issue closes or gets renumbered. Comments should describe the invariant/why in general terms; the origin belongs in the commit message or PR description instead.
Replace the two standalone "Refresh all"/"Fill in missing" buttons with a single "Refresh metadata" button (next to "Add custom game") that opens a modal with a mode dropdown and a Start button. Editing a game with the "Missing info" badge now highlights exactly the blank fields (amber label + exclamation icon + ring on the input), computed from the same fields the badge itself is based on, so it's obvious what to fill in without guessing.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
detectInputsonly recognized an already-processed game folder if the database had a matchingGamerow. On a fresh database (reinstall) or a library arranged outside of a scan, a correctly-structured folder (artwork/+data/*.zip) was queued as raw scan input, then re-matched, compressed into a zip inside itself, and deleted as a "source" once done — silently destroying an already-complete game. Structured folders are now recognized on sight regardless of DB state and are adopted instead of reprocessed."Clair Obscur Expedition 33 - 2025 [305152]"as the title).POST /api/games/refresh-metadata), behind a single "Refresh metadata" button (next to "Add custom game") that opens a modal with a mode dropdown and a Start button: "Refresh all" unconditionally re-fetches metadata + artwork for every game (fixes wrong-but-present fields); "Find missing metadata" only fills in blank fields, leaving everything else untouched. Neither ever moves/renamesgamePath/archivePath— a metadata correction stays a cheap update, not a relocation.AGENTS.md: keep comments general, skip tracker issue references (they rot once an issue closes/renumbers), and don't force a comment where the code already reads clearly.Test plan
api:npm test— 87 tests passing (scanner, naming, metadata refresher, games routes)web:npm test— 5 tests passing, plus a production build