Add a new scheduled task that syncs RetroAchievements progress for all
users with a RetroAchievements username.
Environment variables:
- `ENABLE_SCHEDULED_RETROACHIEVEMENTS_PROGRESS_SYNC`: Enable or disable
the task (default: `false`)
- `SCHEDULED_RETROACHIEVEMENTS_PROGRESS_SYNC_CRON`: Cron string to
schedule the task (default: "0 4 * * *" - daily at 4 AM)
Add a new service adapter for the IGDB API, to separate concerns with
RomM's handler for metadata. This adapter is agnostic to the handler and
only provides methods to interact with the API, and correctly return
typed responses.
The API authorization was also improved to not rely on decorating each
method that makes requests, but instead using an `aiohttp` middleware
to automatically add the required headers to each request.
Utils `mark_expanded` and `mark_list_expanded` where added to help
narrow the types of IGDB's expandable fields when we know they are
expanded, for `mypy` type checking.
This change makes the RetroAchievements progression sync endpoint to
optionally perform an incremental sync (when `incremental` is true),
by only fetching new achievements since the last sync.
This reduces the amount of data fetched and speeds up the sync
process for users who frequently sync their progression. It unblocks the
implementation of automatic periodic syncs in the future.
Frontend behavior:
- When the `Apply` button is clicked in the RetroAchievements settings,
a full sync is performed (same as before). This is because a change to
the RA username may have occurred.
- When the `Sync` button is clicked, an incremental sync is performed.
Guarantee that cache is initialized during startup, and only once,
instead of every time a `MetadataHandler` object is instantiated.
Also, improve logic to determine `fixtures` paths.
When retrieving the related screenshot for a `Save` or `State`, we were
retrieving a very heavy representation of the associated `Rom` object,
only to iterate through its screenshots to find the one we needed.
This change modifies the `Save` and `State` models to directly query the
`Screenshot` model, which is much faster and more efficient. The
`DBScreenshotsHandler` has been updated to include a new `filter` method
that will simplify building queries using SQLAlchemy, something we can
extend to other handlers in the future.
Fixes#1925.