Convert `MetadataHandler` to an abstract base class and add an
`is_enabled` class method that allows every metadata handler to
independently report whether it is enabled based on its configuration.
This avoids the need for global variables in the config module, allowing
us to change the enabled state of a metadata handler at runtime if
needed.
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.