feat(music): add TheAudioDB metadata provider#3124
Conversation
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
📝 WalkthroughWalkthroughThis PR integrates TheAudioDB as a configurable artwork provider into Seerr. It adds a complete data model, API client, backend routes, admin UI, and documentation for managing TheAudioDB credentials and rate limits with connectivity testing. ChangesTheAudioDB Artwork Provider Integration
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Suggested reviewers
🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Pull request overview
Note
Copilot was unable to run its full agentic suite in this review.
Adds configurable “Artwork Providers” settings (TheAudioDB) with server-side persistence, connectivity testing, caching, UI controls, OpenAPI updates, and user documentation.
Changes:
- Introduces settings storage + API routes for artwork providers, including a
/testendpoint. - Adds TheAudioDB API client with cache + rate limiting controls.
- Extends Settings → Metadata Providers UI to configure/test TheAudioDB and show status.
Reviewed changes
Copilot reviewed 12 out of 12 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| src/i18n/locale/en.json | Adds UI strings for artwork provider configuration and TheAudioDB status messaging. |
| src/components/Settings/SettingsMetadata.tsx | Adds Artwork Providers Configuration UI, fetch/save/test flows, and status badge for TheAudioDB. |
| server/routes/settings/index.ts | Registers new /settings/artwork-providers router. |
| server/routes/settings/artworkProviders.ts | Implements GET/PUT settings persistence and POST connectivity test for TheAudioDB. |
| server/routes/settings/artworkProviders.test.ts | Adds route-level tests for settings merge/defaults and connectivity test behavior. |
| server/lib/settings/index.ts | Adds persisted settings schema/defaults + accessors for artwork providers. |
| server/lib/cache.ts | Adds dedicated cache bucket for TheAudioDB. |
| server/api/theaudiodb/interfaces.ts | Adds response typing for TheAudioDB artist lookup. |
| server/api/theaudiodb/index.ts | Adds TheAudioDB client with caching, rate limit config, and connectivity test. |
| server/api/theaudiodb/theaudiodb.test.ts | Adds unit tests for TheAudioDB client behavior and request construction. |
| seerr-api.yml | Documents new settings endpoints and schemas for artwork providers. |
| docs/using-seerr/settings/artwork-providers.md | Documents new Artwork Providers settings page and TheAudioDB configuration. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| const failures: string[] = []; | ||
| if (resp.tvdb === 'failed') { | ||
| failures.push(intl.formatMessage(messages.tvdbProviderDoesnotWork)); | ||
| } | ||
| if (resp.tmdb === 'failed') { | ||
| failures.push(intl.formatMessage(messages.tmdbProviderDoesnotWork)); | ||
| } | ||
| if (resp.theAudioDb === 'failed') { | ||
| failures.push( | ||
| intl.formatMessage(messages.theAudioDbProviderDoesnotWork) | ||
| ); | ||
| } | ||
|
|
||
| if (failures.length > 0) { | ||
| for (const msg of failures) { | ||
| addToast(msg, { appearance: 'error', autoDismiss: true }); | ||
| } | ||
| } else { | ||
| addToast( | ||
| intl.formatMessage(messages.allChosenProvidersAreOperational), | ||
| { appearance: 'success', autoDismiss: true } | ||
| ); | ||
| } |
| const runArtworkProviderTests = async (): Promise<void> => { | ||
| setIsTesting(true); | ||
| try { | ||
| const resp = await axios | ||
| .post<{ | ||
| success: boolean; | ||
| tests: { | ||
| theAudioDb: ProviderStatus; | ||
| }; | ||
| }>('/api/v1/settings/artwork-providers/test') | ||
| .then((r) => r.data.tests) | ||
| .catch((e) => { | ||
| if (axios.isAxiosError(e) && e.response?.data?.tests) { | ||
| return e.response.data.tests as { | ||
| theAudioDb: ProviderStatus; | ||
| }; | ||
| } | ||
| return { | ||
| theAudioDb: 'failed' as const, | ||
| }; | ||
| }); |
| | Field | Default | Description | | ||
| | --------------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | ||
| | **API key** | `195003` | Your TheAudioDB API key. Defaults to the public test key shared by the community; supply your own from [theaudiodb.com](https://www.theaudiodb.com) for production use and higher limits. | | ||
| | **Max requests per second** | `25` | Outbound rate limit. | | ||
| | **Max concurrent requests** | `20` | Cap on in-flight requests. | |
| requestBody: | ||
| required: true | ||
| content: | ||
| application/json: | ||
| schema: | ||
| $ref: '#/components/schemas/ArtworkProvidersSettings' |
e2ad9b7 to
284d395
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/components/Settings/SettingsMetadata.tsx`:
- Around line 580-592: The form currently uses hardcoded fallback defaults in
initialValues (artworkData ?? { theAudioDb: {...} }), which lets a user save
those defaults before SWR finishes and overwrite real settings; change
initialValues to use artworkData only (initialValues={artworkData}) and prevent
rendering/submission while artworkData is undefined — e.g., conditionally render
the form or show a loading state when artworkData is null and disable the submit
button until data loads; ensure the onSubmit handler (the axios.put call and
subsequent mutateArtwork) only runs when artworkData is present so you never
send the fallback defaults to /api/v1/settings/artwork-providers.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 3c78919d-a542-4173-a02f-4b6d35aa8199
📒 Files selected for processing (12)
docs/using-seerr/settings/artwork-providers.mdseerr-api.ymlserver/api/theaudiodb/index.tsserver/api/theaudiodb/interfaces.tsserver/api/theaudiodb/theaudiodb.test.tsserver/lib/cache.tsserver/lib/settings/index.tsserver/routes/settings/artworkProviders.test.tsserver/routes/settings/artworkProviders.tsserver/routes/settings/index.tssrc/components/Settings/SettingsMetadata.tsxsrc/i18n/locale/en.json
| initialValues={ | ||
| artworkData ?? { | ||
| theAudioDb: { apiKey: '195003', maxRPS: 25, maxRequests: 20 }, | ||
| } | ||
| } | ||
| enableReinitialize | ||
| onSubmit={async (values) => { | ||
| try { | ||
| const resp = await axios.put<{ | ||
| success: boolean; | ||
| theAudioDb: TheAudioDbSettings; | ||
| }>('/api/v1/settings/artwork-providers', values); | ||
| mutateArtwork({ |
There was a problem hiding this comment.
Prevent overwriting saved artwork settings before SWR data loads.
Line 581 initializes the form with hardcoded defaults when artworkData is still undefined. If Save is clicked before the fetch resolves, the PUT request can overwrite a previously configured API key/rate limits with fallback values.
Suggested fix
- const { data: artworkData, mutate: mutateArtwork } =
- useSWR<ArtworkProvidersSettings>('/api/v1/settings/artwork-providers');
+ const {
+ data: artworkData,
+ error: artworkError,
+ mutate: mutateArtwork,
+ } = useSWR<ArtworkProvidersSettings>('/api/v1/settings/artwork-providers');
+
+ const artworkLoading = !artworkData && !artworkError;
- if (!data && !error) {
+ if ((!data && !error) || artworkLoading) {
return <LoadingSpinner />;
}
...
- initialValues={
- artworkData ?? {
- theAudioDb: { apiKey: '195003', maxRPS: 25, maxRequests: 20 },
- }
- }
+ initialValues={artworkData}🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/components/Settings/SettingsMetadata.tsx` around lines 580 - 592, The
form currently uses hardcoded fallback defaults in initialValues (artworkData ??
{ theAudioDb: {...} }), which lets a user save those defaults before SWR
finishes and overwrite real settings; change initialValues to use artworkData
only (initialValues={artworkData}) and prevent rendering/submission while
artworkData is undefined — e.g., conditionally render the form or show a loading
state when artworkData is null and disable the submit button until data loads;
ensure the onSubmit handler (the axios.put call and subsequent mutateArtwork)
only runs when artworkData is present so you never send the fallback defaults to
/api/v1/settings/artwork-providers.
|
This pull request has merge conflicts. Please resolve the conflicts so the PR can be successfully reviewed and merged. |
2676b77 to
2d7267a
Compare
Description
This adds the TheAudioDB metadata provider for use in fetching music cover art
In the future these can be expanded to include persistent caching using the database to track caching (like done in #2132), however this is technically not needed to have these providers fully-functional and allows for improved review ability.
Adds standalone TheAudioDB client along with admin settings, route, UI and OpenAPI documentation so their API surface, rate limiting and credentials can be validated before any music features consume them.
Changes:
AI usage:
Structural coding and GUI review/design done manually
Architectural design mostly done in original music PR.
How Has This Been Tested?
Screenshots / Logs (if applicable)
Checklist:
pnpm buildpnpm i18n:extractSummary by CodeRabbit
Release Notes
New Features
Documentation