feat(api): add excludeKeywords parameter to discovery queries (#1908)
Signed-off-by: 0xsysr3ll <0xsysr3ll@pm.me>
This commit is contained in:
@@ -5198,6 +5198,12 @@ paths:
|
|||||||
schema:
|
schema:
|
||||||
type: string
|
type: string
|
||||||
example: 1,2
|
example: 1,2
|
||||||
|
- in: query
|
||||||
|
name: excludeKeywords
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
example: 3,4
|
||||||
|
description: Comma-separated list of keyword IDs to exclude from results
|
||||||
- in: query
|
- in: query
|
||||||
name: sortBy
|
name: sortBy
|
||||||
schema:
|
schema:
|
||||||
@@ -5518,6 +5524,12 @@ paths:
|
|||||||
schema:
|
schema:
|
||||||
type: string
|
type: string
|
||||||
example: 1,2
|
example: 1,2
|
||||||
|
- in: query
|
||||||
|
name: excludeKeywords
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
example: 3,4
|
||||||
|
description: Comma-separated list of keyword IDs to exclude from results
|
||||||
- in: query
|
- in: query
|
||||||
name: sortBy
|
name: sortBy
|
||||||
schema:
|
schema:
|
||||||
|
|||||||
@@ -86,6 +86,7 @@ interface DiscoverMovieOptions {
|
|||||||
genre?: string;
|
genre?: string;
|
||||||
studio?: string;
|
studio?: string;
|
||||||
keywords?: string;
|
keywords?: string;
|
||||||
|
excludeKeywords?: string;
|
||||||
sortBy?: SortOptions;
|
sortBy?: SortOptions;
|
||||||
watchRegion?: string;
|
watchRegion?: string;
|
||||||
watchProviders?: string;
|
watchProviders?: string;
|
||||||
@@ -111,6 +112,7 @@ interface DiscoverTvOptions {
|
|||||||
genre?: string;
|
genre?: string;
|
||||||
network?: number;
|
network?: number;
|
||||||
keywords?: string;
|
keywords?: string;
|
||||||
|
excludeKeywords?: string;
|
||||||
sortBy?: SortOptions;
|
sortBy?: SortOptions;
|
||||||
watchRegion?: string;
|
watchRegion?: string;
|
||||||
watchProviders?: string;
|
watchProviders?: string;
|
||||||
@@ -495,6 +497,7 @@ class TheMovieDb extends ExternalAPI implements TvShowProvider {
|
|||||||
genre,
|
genre,
|
||||||
studio,
|
studio,
|
||||||
keywords,
|
keywords,
|
||||||
|
excludeKeywords,
|
||||||
withRuntimeGte,
|
withRuntimeGte,
|
||||||
withRuntimeLte,
|
withRuntimeLte,
|
||||||
voteAverageGte,
|
voteAverageGte,
|
||||||
@@ -545,6 +548,7 @@ class TheMovieDb extends ExternalAPI implements TvShowProvider {
|
|||||||
with_genres: genre,
|
with_genres: genre,
|
||||||
with_companies: studio,
|
with_companies: studio,
|
||||||
with_keywords: keywords,
|
with_keywords: keywords,
|
||||||
|
without_keywords: excludeKeywords,
|
||||||
'with_runtime.gte': withRuntimeGte,
|
'with_runtime.gte': withRuntimeGte,
|
||||||
'with_runtime.lte': withRuntimeLte,
|
'with_runtime.lte': withRuntimeLte,
|
||||||
'vote_average.gte': voteAverageGte,
|
'vote_average.gte': voteAverageGte,
|
||||||
@@ -577,6 +581,7 @@ class TheMovieDb extends ExternalAPI implements TvShowProvider {
|
|||||||
genre,
|
genre,
|
||||||
network,
|
network,
|
||||||
keywords,
|
keywords,
|
||||||
|
excludeKeywords,
|
||||||
withRuntimeGte,
|
withRuntimeGte,
|
||||||
withRuntimeLte,
|
withRuntimeLte,
|
||||||
voteAverageGte,
|
voteAverageGte,
|
||||||
@@ -628,6 +633,7 @@ class TheMovieDb extends ExternalAPI implements TvShowProvider {
|
|||||||
with_genres: genre,
|
with_genres: genre,
|
||||||
with_networks: network,
|
with_networks: network,
|
||||||
with_keywords: keywords,
|
with_keywords: keywords,
|
||||||
|
without_keywords: excludeKeywords,
|
||||||
'with_runtime.gte': withRuntimeGte,
|
'with_runtime.gte': withRuntimeGte,
|
||||||
'with_runtime.lte': withRuntimeLte,
|
'with_runtime.lte': withRuntimeLte,
|
||||||
'vote_average.gte': voteAverageGte,
|
'vote_average.gte': voteAverageGte,
|
||||||
|
|||||||
@@ -61,6 +61,7 @@ const QueryFilterOptions = z.object({
|
|||||||
studio: z.coerce.string().optional(),
|
studio: z.coerce.string().optional(),
|
||||||
genre: z.coerce.string().optional(),
|
genre: z.coerce.string().optional(),
|
||||||
keywords: z.coerce.string().optional(),
|
keywords: z.coerce.string().optional(),
|
||||||
|
excludeKeywords: z.coerce.string().optional(),
|
||||||
language: z.coerce.string().optional(),
|
language: z.coerce.string().optional(),
|
||||||
withRuntimeGte: z.coerce.string().optional(),
|
withRuntimeGte: z.coerce.string().optional(),
|
||||||
withRuntimeLte: z.coerce.string().optional(),
|
withRuntimeLte: z.coerce.string().optional(),
|
||||||
@@ -90,6 +91,7 @@ discoverRoutes.get('/movies', async (req, res, next) => {
|
|||||||
try {
|
try {
|
||||||
const query = ApiQuerySchema.parse(req.query);
|
const query = ApiQuerySchema.parse(req.query);
|
||||||
const keywords = query.keywords;
|
const keywords = query.keywords;
|
||||||
|
const excludeKeywords = query.excludeKeywords;
|
||||||
|
|
||||||
const data = await tmdb.getDiscoverMovies({
|
const data = await tmdb.getDiscoverMovies({
|
||||||
page: Number(query.page),
|
page: Number(query.page),
|
||||||
@@ -105,6 +107,7 @@ discoverRoutes.get('/movies', async (req, res, next) => {
|
|||||||
? new Date(query.primaryReleaseDateGte).toISOString().split('T')[0]
|
? new Date(query.primaryReleaseDateGte).toISOString().split('T')[0]
|
||||||
: undefined,
|
: undefined,
|
||||||
keywords,
|
keywords,
|
||||||
|
excludeKeywords,
|
||||||
withRuntimeGte: query.withRuntimeGte,
|
withRuntimeGte: query.withRuntimeGte,
|
||||||
withRuntimeLte: query.withRuntimeLte,
|
withRuntimeLte: query.withRuntimeLte,
|
||||||
voteAverageGte: query.voteAverageGte,
|
voteAverageGte: query.voteAverageGte,
|
||||||
@@ -381,6 +384,7 @@ discoverRoutes.get('/tv', async (req, res, next) => {
|
|||||||
try {
|
try {
|
||||||
const query = ApiQuerySchema.parse(req.query);
|
const query = ApiQuerySchema.parse(req.query);
|
||||||
const keywords = query.keywords;
|
const keywords = query.keywords;
|
||||||
|
const excludeKeywords = query.excludeKeywords;
|
||||||
const data = await tmdb.getDiscoverTv({
|
const data = await tmdb.getDiscoverTv({
|
||||||
page: Number(query.page),
|
page: Number(query.page),
|
||||||
sortBy: query.sortBy as SortOptions,
|
sortBy: query.sortBy as SortOptions,
|
||||||
@@ -395,6 +399,7 @@ discoverRoutes.get('/tv', async (req, res, next) => {
|
|||||||
: undefined,
|
: undefined,
|
||||||
originalLanguage: query.language,
|
originalLanguage: query.language,
|
||||||
keywords,
|
keywords,
|
||||||
|
excludeKeywords,
|
||||||
withRuntimeGte: query.withRuntimeGte,
|
withRuntimeGte: query.withRuntimeGte,
|
||||||
withRuntimeLte: query.withRuntimeLte,
|
withRuntimeLte: query.withRuntimeLte,
|
||||||
voteAverageGte: query.voteAverageGte,
|
voteAverageGte: query.voteAverageGte,
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ const messages = defineMessages('components.Discover.FilterSlideover', {
|
|||||||
studio: 'Studio',
|
studio: 'Studio',
|
||||||
genres: 'Genres',
|
genres: 'Genres',
|
||||||
keywords: 'Keywords',
|
keywords: 'Keywords',
|
||||||
|
excludeKeywords: 'Exclude Keywords',
|
||||||
originalLanguage: 'Original Language',
|
originalLanguage: 'Original Language',
|
||||||
runtimeText: '{minValue}-{maxValue} minute runtime',
|
runtimeText: '{minValue}-{maxValue} minute runtime',
|
||||||
ratingText: 'Ratings between {minValue} and {maxValue}',
|
ratingText: 'Ratings between {minValue} and {maxValue}',
|
||||||
@@ -181,6 +182,19 @@ const FilterSlideover = ({
|
|||||||
updateQueryParams('keywords', value?.map((v) => v.value).join(','));
|
updateQueryParams('keywords', value?.map((v) => v.value).join(','));
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
<span className="text-lg font-semibold">
|
||||||
|
{intl.formatMessage(messages.excludeKeywords)}
|
||||||
|
</span>
|
||||||
|
<KeywordSelector
|
||||||
|
defaultValue={currentFilters.excludeKeywords}
|
||||||
|
isMulti
|
||||||
|
onChange={(value) => {
|
||||||
|
updateQueryParams(
|
||||||
|
'excludeKeywords',
|
||||||
|
value?.map((v) => v.value).join(',')
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
<span className="text-lg font-semibold">
|
<span className="text-lg font-semibold">
|
||||||
{intl.formatMessage(messages.originalLanguage)}
|
{intl.formatMessage(messages.originalLanguage)}
|
||||||
</span>
|
</span>
|
||||||
|
|||||||
@@ -99,6 +99,7 @@ export const QueryFilterOptions = z.object({
|
|||||||
studio: z.string().optional(),
|
studio: z.string().optional(),
|
||||||
genre: z.string().optional(),
|
genre: z.string().optional(),
|
||||||
keywords: z.string().optional(),
|
keywords: z.string().optional(),
|
||||||
|
excludeKeywords: z.string().optional(),
|
||||||
language: z.string().optional(),
|
language: z.string().optional(),
|
||||||
withRuntimeGte: z.string().optional(),
|
withRuntimeGte: z.string().optional(),
|
||||||
withRuntimeLte: z.string().optional(),
|
withRuntimeLte: z.string().optional(),
|
||||||
@@ -161,6 +162,10 @@ export const prepareFilterValues = (
|
|||||||
filterValues.keywords = values.keywords;
|
filterValues.keywords = values.keywords;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (values.excludeKeywords) {
|
||||||
|
filterValues.excludeKeywords = values.excludeKeywords;
|
||||||
|
}
|
||||||
|
|
||||||
if (values.language) {
|
if (values.language) {
|
||||||
filterValues.language = values.language;
|
filterValues.language = values.language;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -78,6 +78,7 @@
|
|||||||
"components.Discover.FilterSlideover.activefilters": "{count, plural, one {# Active Filter} other {# Active Filters}}",
|
"components.Discover.FilterSlideover.activefilters": "{count, plural, one {# Active Filter} other {# Active Filters}}",
|
||||||
"components.Discover.FilterSlideover.certification": "Content Rating",
|
"components.Discover.FilterSlideover.certification": "Content Rating",
|
||||||
"components.Discover.FilterSlideover.clearfilters": "Clear Active Filters",
|
"components.Discover.FilterSlideover.clearfilters": "Clear Active Filters",
|
||||||
|
"components.Discover.FilterSlideover.excludeKeywords": "Exclude Keywords",
|
||||||
"components.Discover.FilterSlideover.filters": "Filters",
|
"components.Discover.FilterSlideover.filters": "Filters",
|
||||||
"components.Discover.FilterSlideover.firstAirDate": "First Air Date",
|
"components.Discover.FilterSlideover.firstAirDate": "First Air Date",
|
||||||
"components.Discover.FilterSlideover.from": "From",
|
"components.Discover.FilterSlideover.from": "From",
|
||||||
|
|||||||
Reference in New Issue
Block a user