diff --git a/src/backend/metadata/search.ts b/src/backend/metadata/search.ts index 08671db7..2bbee195 100644 --- a/src/backend/metadata/search.ts +++ b/src/backend/metadata/search.ts @@ -7,6 +7,8 @@ import { getMediaDetails, getMediaPoster, multiSearch, + searchMovies, + searchTVShows, } from "./tmdb"; import { TMDBContentTypes } from "./types/tmdb"; @@ -26,6 +28,9 @@ const tmdbIdPattern = /^tmdb:(\d+)(?::(movie|tv))?$/i; // detect "year:YYYY" const yearPattern = /(.+?)\s+year:(\d{4})$/i; +// detect "type:movie" or "type:tv" +const typePattern = /(.+?)\s+type:(movie|tv)$/i; + export async function searchForMedia(query: MWQuery): Promise { if (cache.has(query)) return cache.get(query) as MediaItem[]; const { searchQuery } = query; @@ -82,8 +87,25 @@ export async function searchForMedia(query: MWQuery): Promise { yearValue = yearMatch[2]; } - // normal search - const data = await multiSearch(queryWithoutYear); + // type extract logic + let typeValue: string | undefined; + let queryWithoutType = queryWithoutYear; + + const typeMatch = queryWithoutYear.match(typePattern); + if (typeMatch && typeMatch[2]) { + queryWithoutType = typeMatch[1].trim(); + typeValue = typeMatch[2].toLowerCase(); + } + + let data: any[]; + if (typeValue === "movie") { + data = await searchMovies(queryWithoutType); + } else if (typeValue === "tv") { + data = await searchTVShows(queryWithoutType); + } else { + data = await multiSearch(queryWithoutType); + } + let results = data.map((v) => { const formattedResult = formatTMDBSearchResult(v, v.media_type); return formatTMDBMetaToMediaItem(formattedResult); diff --git a/src/backend/metadata/tmdb.ts b/src/backend/metadata/tmdb.ts index 875046e7..92628fe2 100644 --- a/src/backend/metadata/tmdb.ts +++ b/src/backend/metadata/tmdb.ts @@ -248,6 +248,38 @@ export async function multiSearch( return results; } +export async function searchMovies( + query: string, +): Promise { + const data = await get<{ + results: TMDBMovieSearchResult[]; + }>("search/movie", { + query, + include_adult: false, + page: 1, + }); + return data.results.map((result) => ({ + ...result, + media_type: TMDBContentTypes.MOVIE, + })); +} + +export async function searchTVShows( + query: string, +): Promise { + const data = await get<{ + results: TMDBShowSearchResult[]; + }>("search/tv", { + query, + include_adult: false, + page: 1, + }); + return data.results.map((result) => ({ + ...result, + media_type: TMDBContentTypes.TV, + })); +} + export async function generateQuickSearchMediaUrl( query: string, ): Promise { diff --git a/src/components/form/SearchBar.tsx b/src/components/form/SearchBar.tsx index 6ef95665..b86abcd3 100644 --- a/src/components/form/SearchBar.tsx +++ b/src/components/form/SearchBar.tsx @@ -114,6 +114,15 @@ export const SearchBarInput = forwardRef( Inception year:2010

+
+

Type search:

+

+ Marvel type:movie +

+

+ Friends type:tv +

+

TMDB ID search: