diff --git a/jellyseerr-api.yml b/jellyseerr-api.yml index 86644b44c..841e119ba 100644 --- a/jellyseerr-api.yml +++ b/jellyseerr-api.yml @@ -7268,21 +7268,12 @@ paths: example: 1 responses: '200': - description: Keyword returned + description: Keyword returned (null if not found) content: application/json: schema: + nullable: true $ref: '#/components/schemas/Keyword' - '404': - description: Keyword not found - content: - application/json: - schema: - type: object - properties: - message: - type: string - example: 'Keyword not found' '500': description: Internal server error content: diff --git a/server/api/themoviedb/index.ts b/server/api/themoviedb/index.ts index dcb94aeca..9d6f5089b 100644 --- a/server/api/themoviedb/index.ts +++ b/server/api/themoviedb/index.ts @@ -1054,7 +1054,7 @@ class TheMovieDb extends ExternalAPI { keywordId, }: { keywordId: number; - }): Promise { + }): Promise { try { const data = await this.get( `/keyword/${keywordId}`, @@ -1065,7 +1065,7 @@ class TheMovieDb extends ExternalAPI { return data; } catch (e) { if (e.response?.status === 404) { - throw e; + return null; } throw new Error(`[TMDB] Failed to fetch keyword: ${e.message}`); } diff --git a/server/job/blacklistedTagsProcessor.ts b/server/job/blacklistedTagsProcessor.ts index d35caa1b5..f7ca4f0f2 100644 --- a/server/job/blacklistedTagsProcessor.ts +++ b/server/job/blacklistedTagsProcessor.ts @@ -88,24 +88,17 @@ class BlacklistedTagProcessor implements RunnableScanner { // Iterate for each tag for (const tag of blacklistedTagsArr) { - try { - await tmdb.getKeywordDetails({ keywordId: Number(tag) }); - } catch (error) { - if (error.response?.status === 404) { - logger.warn('Skipping invalid keyword in blacklisted tags', { - label: 'Blacklisted Tags Processor', - keywordId: tag, - }); - invalidKeywords.add(tag); - continue; - } else { - // Might be temporary service issues so do nothing - logger.error('Error checking keyword validity', { - label: 'Blacklisted Tags Processor', - keywordId: tag, - errorMessage: error.message, - }); - } + const keywordDetails = await tmdb.getKeywordDetails({ + keywordId: Number(tag), + }); + + if (keywordDetails === null) { + logger.warn('Skipping invalid keyword in blacklisted tags', { + label: 'Blacklisted Tags Processor', + keywordId: tag, + }); + invalidKeywords.add(tag); + continue; } let queryMax = pageLimit * SortOptionsIterable.length; diff --git a/server/routes/discover.ts b/server/routes/discover.ts index 72688b2f3..4fdd11678 100644 --- a/server/routes/discover.ts +++ b/server/routes/discover.ts @@ -128,11 +128,15 @@ discoverRoutes.get('/movies', async (req, res, next) => { if (keywords) { const splitKeywords = keywords.split(','); - keywordData = await Promise.all( + const keywordResults = await Promise.all( splitKeywords.map(async (keywordId) => { return await tmdb.getKeywordDetails({ keywordId: Number(keywordId) }); }) ); + + keywordData = keywordResults.filter( + (keyword): keyword is TmdbKeyword => keyword !== null + ); } return res.status(200).json({ @@ -415,11 +419,15 @@ discoverRoutes.get('/tv', async (req, res, next) => { if (keywords) { const splitKeywords = keywords.split(','); - keywordData = await Promise.all( + const keywordResults = await Promise.all( splitKeywords.map(async (keywordId) => { return await tmdb.getKeywordDetails({ keywordId: Number(keywordId) }); }) ); + + keywordData = keywordResults.filter( + (keyword): keyword is TmdbKeyword => keyword !== null + ); } return res.status(200).json({ diff --git a/server/routes/index.ts b/server/routes/index.ts index dedc7b680..b28421396 100644 --- a/server/routes/index.ts +++ b/server/routes/index.ts @@ -330,10 +330,6 @@ router.get('/keyword/:keywordId', async (req, res, next) => { return res.status(200).json(result); } catch (e) { - if (e.response?.status === 404) { - return res.status(404).json({ message: 'Keyword not found' }); - } - logger.debug('Something went wrong retrieving keyword data', { label: 'API', errorMessage: e.message, diff --git a/src/components/BlacklistedTagsBadge/index.tsx b/src/components/BlacklistedTagsBadge/index.tsx index b57f5df56..a96272a4b 100644 --- a/src/components/BlacklistedTagsBadge/index.tsx +++ b/src/components/BlacklistedTagsBadge/index.tsx @@ -29,21 +29,13 @@ const BlacklistedTagsBadge = ({ data }: BlacklistedTagsBadgeProps) => { const keywordIds = data.blacklistedTags.slice(1, -1).split(','); Promise.all( keywordIds.map(async (keywordId) => { - try { - const { data } = await axios.get( - `/api/v1/keyword/${keywordId}` - ); - return data.name; - } catch (err) { - if (err.response?.status === 404) { - return `[Invalid: ${keywordId}]`; - } - return ''; - } + const { data } = await axios.get( + `/api/v1/keyword/${keywordId}` + ); + return data?.name || `[Invalid: ${keywordId}]`; }) ).then((keywords) => { - const validKeywords = keywords.filter((name) => name !== ''); - setTagNamesBlacklistedFor(validKeywords.join(', ')); + setTagNamesBlacklistedFor(keywords.join(', ')); }); }, [data.blacklistedTags]); diff --git a/src/components/BlacklistedTagsSelector/index.tsx b/src/components/BlacklistedTagsSelector/index.tsx index e318b0935..fadbfad2b 100644 --- a/src/components/BlacklistedTagsSelector/index.tsx +++ b/src/components/BlacklistedTagsSelector/index.tsx @@ -5,10 +5,7 @@ import { encodeURIExtraParams } from '@app/hooks/useDiscover'; import defineMessages from '@app/utils/defineMessages'; import { Transition } from '@headlessui/react'; import { ArrowDownIcon } from '@heroicons/react/24/solid'; -import type { - TmdbKeyword, - TmdbKeywordSearchResponse, -} from '@server/api/themoviedb/interfaces'; +import type { TmdbKeywordSearchResponse } from '@server/api/themoviedb/interfaces'; import type { Keyword } from '@server/models/common'; import axios from 'axios'; import { useFormikContext } from 'formik'; @@ -127,19 +124,15 @@ const ControlledKeywordSelector = ({ const keywords = await Promise.all( defaultValue.split(',').map(async (keywordId) => { - try { - const { data } = await axios.get( - `/api/v1/keyword/${keywordId}` - ); - return data; - } catch (error) { - return null; - } + const { data } = await axios.get( + `/api/v1/keyword/${keywordId}` + ); + return data; }) ); - const validKeywords: TmdbKeyword[] = keywords.filter( - (keyword) => keyword !== null + const validKeywords = keywords.filter( + (keyword): keyword is Keyword => keyword !== null ); onChange( diff --git a/src/components/Discover/CreateSlider/index.tsx b/src/components/Discover/CreateSlider/index.tsx index 32cca0794..62df303f2 100644 --- a/src/components/Discover/CreateSlider/index.tsx +++ b/src/components/Discover/CreateSlider/index.tsx @@ -77,16 +77,19 @@ const CreateSlider = ({ onCreate, slider }: CreateSliderProps) => { const keywords = await Promise.all( slider.data.split(',').map(async (keywordId) => { - const keyword = await axios.get( + const keyword = await axios.get( `/api/v1/keyword/${keywordId}` ); - return keyword.data; }) ); + const validKeywords = keywords.filter( + (keyword): keyword is Keyword => keyword !== null + ); + setDefaultDataValue( - keywords.map((keyword) => ({ + validKeywords.map((keyword) => ({ label: keyword.name, value: keyword.id, })) diff --git a/src/components/Selector/index.tsx b/src/components/Selector/index.tsx index e6eb15ff4..06fb52331 100644 --- a/src/components/Selector/index.tsx +++ b/src/components/Selector/index.tsx @@ -309,16 +309,19 @@ export const KeywordSelector = ({ const keywords = await Promise.all( defaultValue.split(',').map(async (keywordId) => { - const keyword = await axios.get( + const keyword = await axios.get( `/api/v1/keyword/${keywordId}` ); - return keyword.data; }) ); + const validKeywords = keywords.filter( + (keyword): keyword is Keyword => keyword !== null + ); + setDefaultDataValue( - keywords.map((keyword) => ({ + validKeywords.map((keyword) => ({ label: keyword.name, value: keyword.id, })) diff --git a/src/components/Settings/OverrideRule/OverrideRuleTiles.tsx b/src/components/Settings/OverrideRule/OverrideRuleTiles.tsx index 4208836f8..dcc3c267c 100644 --- a/src/components/Settings/OverrideRule/OverrideRuleTiles.tsx +++ b/src/components/Settings/OverrideRule/OverrideRuleTiles.tsx @@ -113,12 +113,16 @@ const OverrideRuleTiles = ({ .flat() .filter((keywordId) => keywordId) .map(async (keywordId) => { - const response = await axios.get(`/api/v1/keyword/${keywordId}`); - const keyword: Keyword = response.data; - return keyword; + const response = await axios.get( + `/api/v1/keyword/${keywordId}` + ); + return response.data; }) ); - setKeywords(keywords); + const validKeywords = keywords.filter( + (keyword): keyword is Keyword => keyword !== null + ); + setKeywords(validKeywords); const allUsersFromRules = rules .map((rule) => rule.users) .filter((users) => users)