Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"build": "pnpm build:next && pnpm build:server",
"lint": "eslint \"./server/**/*.{ts,tsx}\" \"./src/**/*.{ts,tsx}\" --cache",
"lintfix": "eslint \"./server/**/*.{ts,tsx}\" \"./src/**/*.{ts,tsx}\" --fix",
"test": "node server/test/index.mts",
"test": "node --experimental-strip-types server/test/index.mts",
"start": "NODE_ENV=production node dist/index.js",
"i18n:extract": "ts-node --project server/tsconfig.json src/i18n/extractMessages.ts",
"migration:generate": "ts-node -r tsconfig-paths/register --project server/tsconfig.json ./node_modules/typeorm/cli.js migration:generate -d server/datasource.ts",
Expand Down
8 changes: 8 additions & 0 deletions seerr-api.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5225,6 +5225,13 @@ paths:
schema:
type: string
example: en
- in: query
name: searchType
schema:
type: string
enum: ['all', 'movie', 'tv', 'person', 'collection']
default: all
example: all
responses:
'200':
description: Results
Expand All @@ -5249,6 +5256,7 @@ paths:
- $ref: '#/components/schemas/MovieResult'
- $ref: '#/components/schemas/TvResult'
- $ref: '#/components/schemas/PersonResult'
- $ref: '#/components/schemas/CollectionResult'
Copy link

Copilot AI Apr 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OpenAPI spec adds CollectionResult to the /search response, but there is no corresponding components/schemas/CollectionResult defined in this file. This makes the spec invalid for generators/validators. Add a CollectionResult schema (matching the API response fields) or reference an existing schema name if one already exists.

Suggested change
- $ref: '#/components/schemas/CollectionResult'
- type: object
properties:
id:
type: number
example: 10
name:
type: string
example: 'Star Wars Collection'
overview:
type: string
example: 'An epic space-opera media franchise.'
posterPath:
type: string
nullable: true
example: '/abc123.jpg'
backdropPath:
type: string
nullable: true
example: '/def456.jpg'
mediaType:
type: string
example: collection

Copilot uses AI. Check for mistakes.
/search/keyword:
get:
summary: Search for keywords
Expand Down
59 changes: 59 additions & 0 deletions server/api/themoviedb/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@ import type {
TmdbPersonDetails,
TmdbProductionCompany,
TmdbRegion,
TmdbSearchCollectionResponse,
TmdbSearchMovieResponse,
TmdbSearchMultiResponse,
TmdbSearchPersonResponse,
TmdbSearchTvResponse,
TmdbSeasonWithEpisodes,
TmdbTvDetails,
Expand Down Expand Up @@ -230,6 +232,63 @@ class TheMovieDb extends ExternalAPI implements TvShowProvider {
}
};

public searchPerson = async ({
query,
page = 1,
includeAdult = false,
language = this.locale,
}: SearchOptions): Promise<TmdbSearchPersonResponse> => {
try {
const data = await this.get<TmdbSearchPersonResponse>('/search/person', {
params: {
query,
page,
include_adult: includeAdult,
language,
},
});

return data;
} catch {
return {
page: 1,
results: [],
total_pages: 1,
total_results: 0,
};
Comment on lines +235 to +258
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Don’t mask TMDB failures as an empty first page.

Both new search paths return { page: 1, total_pages: 1, results: [] } on any upstream error. That makes person/collection searches indistinguishable from a legitimate zero-result query, and for page 2+ failures it tells paginated clients to stop loading more results. Bubble the error, or at least preserve the requested page and log the failure before falling back.

Also applies to: 262-288

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@server/api/themoviedb/index.ts` around lines 235 - 258, The searchPerson
method currently swallows all errors and returns a fake first-page empty result;
change the catch block in searchPerson (and the analogous collection/person
search methods mentioned) to not mask failures: either rethrow the caught error
(throw err) so callers can handle upstream failures, or if you must return a
fallback, log the full error (using your logger) and return the same structure
but preserve the original requested page (use the incoming page variable) and
include error context so paginated clients know not to stop. Update the catch to
capture the error object (catch (err)) and apply this behavior consistently for
the other search methods.

}
};
Comment thread
coderabbitai[bot] marked this conversation as resolved.

public searchCollections = async ({
query,
page = 1,
includeAdult = false,
language = this.locale,
}: SearchOptions): Promise<TmdbSearchCollectionResponse> => {
try {
const data = await this.get<TmdbSearchCollectionResponse>(
'/search/collection',
{
params: {
query,
page,
include_adult: includeAdult,
language,
},
}
);

return data;
} catch {
return {
page: 1,
results: [],
total_pages: 1,
total_results: 0,
};
}
};
Comment thread
coderabbitai[bot] marked this conversation as resolved.

public getPerson = async ({
personId,
language = this.locale,
Expand Down
8 changes: 8 additions & 0 deletions server/api/themoviedb/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,14 @@ export interface TmdbSearchTvResponse extends TmdbPaginatedResponse {
results: TmdbTvResult[];
}

export interface TmdbSearchPersonResponse extends TmdbPaginatedResponse {
results: TmdbPersonResult[];
}

export interface TmdbSearchCollectionResponse extends TmdbPaginatedResponse {
results: TmdbCollectionResult[];
}

export interface TmdbUpcomingMoviesResponse extends TmdbPaginatedResponse {
dates: {
maximum: string;
Expand Down
Loading
Loading