mirror of
https://github.com/Viren070/tmdb-addon.git
synced 2025-12-01 23:18:11 +01:00
feat(ageRating): add age rating in imdb link and genres based on config
This commit is contained in:
+29
-17
@@ -78,16 +78,16 @@ addon.get('/:catalogChoices?/configure', function (req, res) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
addon.get("/:catalogChoices?/manifest.json", async function (req, res) {
|
addon.get("/:catalogChoices?/manifest.json", async function (req, res) {
|
||||||
const { catalogChoices } = req.params;
|
const { catalogChoices } = req.params;
|
||||||
const config = parseConfig(catalogChoices) || {};
|
const config = parseConfig(catalogChoices) || {};
|
||||||
const manifest = await getManifest(config);
|
const manifest = await getManifest(config);
|
||||||
|
|
||||||
const cacheOpts = {
|
const cacheOpts = {
|
||||||
cacheMaxAge: 12 * 60 * 60,
|
cacheMaxAge: 12 * 60 * 60,
|
||||||
staleRevalidate: 14 * 24 * 60 * 60,
|
staleRevalidate: 14 * 24 * 60 * 60,
|
||||||
staleError: 30 * 24 * 60 * 60,
|
staleError: 30 * 24 * 60 * 60,
|
||||||
};
|
};
|
||||||
respond(res, manifest, cacheOpts);
|
respond(res, manifest, cacheOpts);
|
||||||
});
|
});
|
||||||
|
|
||||||
addon.get("/:catalogChoices?/catalog/:type/:id/:extra?.json", async function (req, res) {
|
addon.get("/:catalogChoices?/catalog/:type/:id/:extra?.json", async function (req, res) {
|
||||||
@@ -129,7 +129,7 @@ addon.get("/:catalogChoices?/catalog/:type/:id/:extra?.json", async function (re
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const cacheOpts = {
|
const cacheOpts = {
|
||||||
cacheMaxAge: 1 * 24 * 60 * 60,
|
cacheMaxAge: 1 * 24 * 60 * 60,
|
||||||
staleRevalidate: 7 * 24 * 60 * 60,
|
staleRevalidate: 7 * 24 * 60 * 60,
|
||||||
staleError: 14 * 24 * 60 * 60,
|
staleError: 14 * 24 * 60 * 60,
|
||||||
};
|
};
|
||||||
@@ -137,7 +137,7 @@ addon.get("/:catalogChoices?/catalog/:type/:id/:extra?.json", async function (re
|
|||||||
try {
|
try {
|
||||||
metas = JSON.parse(JSON.stringify(metas));
|
metas = JSON.parse(JSON.stringify(metas));
|
||||||
metas.metas = await Promise.all(metas.metas.map(async (el) => {
|
metas.metas = await Promise.all(metas.metas.map(async (el) => {
|
||||||
const rpdbImage = getRpdbPoster(type, el.id.replace('tmdb:', ''), language, rpdbkey)
|
const rpdbImage = getRpdbPoster(type, el.id.replace('tmdb:', ''), language, rpdbkey)
|
||||||
el.poster = await checkIfExists(rpdbImage) ? rpdbImage : el.poster;
|
el.poster = await checkIfExists(rpdbImage) ? rpdbImage : el.poster;
|
||||||
return el;
|
return el;
|
||||||
}))
|
}))
|
||||||
@@ -156,7 +156,13 @@ addon.get("/:catalogChoices?/meta/:type/:id.json", async function (req, res) {
|
|||||||
|
|
||||||
if (req.params.id.includes("tmdb:")) {
|
if (req.params.id.includes("tmdb:")) {
|
||||||
const resp = await cacheWrapMeta(`${language}:${type}:${tmdbId}`, async () => {
|
const resp = await cacheWrapMeta(`${language}:${type}:${tmdbId}`, async () => {
|
||||||
return await getMeta(type, language, tmdbId, rpdbkey, config);
|
return await getMeta(type, language, tmdbId, rpdbkey, {
|
||||||
|
...config,
|
||||||
|
hideEpisodeThumbnails: config.hideEpisodeThumbnails === "true",
|
||||||
|
enableAgeRating: config.enableAgeRating === "true",
|
||||||
|
showAgeRatingInGenres: config.showAgeRatingInGenres !== "false",
|
||||||
|
showAgeRatingWithImdbRating: config.showAgeRatingWithImdbRating === "true"
|
||||||
|
});
|
||||||
});
|
});
|
||||||
const cacheOpts = {
|
const cacheOpts = {
|
||||||
staleRevalidate: 20 * 24 * 60 * 60,
|
staleRevalidate: 20 * 24 * 60 * 60,
|
||||||
@@ -174,7 +180,13 @@ addon.get("/:catalogChoices?/meta/:type/:id.json", async function (req, res) {
|
|||||||
const tmdbId = await getTmdb(type, imdbId);
|
const tmdbId = await getTmdb(type, imdbId);
|
||||||
if (tmdbId) {
|
if (tmdbId) {
|
||||||
const resp = await cacheWrapMeta(`${language}:${type}:${tmdbId}`, async () => {
|
const resp = await cacheWrapMeta(`${language}:${type}:${tmdbId}`, async () => {
|
||||||
return await getMeta(type, language, tmdbId, rpdbkey, config);
|
return await getMeta(type, language, tmdbId, rpdbkey, {
|
||||||
|
...config,
|
||||||
|
hideEpisodeThumbnails: config.hideEpisodeThumbnails === "true",
|
||||||
|
enableAgeRating: config.enableAgeRating === "true",
|
||||||
|
showAgeRatingInGenres: config.showAgeRatingInGenres !== "false",
|
||||||
|
showAgeRatingWithImdbRating: config.showAgeRatingWithImdbRating === "true"
|
||||||
|
});
|
||||||
});
|
});
|
||||||
const cacheOpts = {
|
const cacheOpts = {
|
||||||
staleRevalidate: 20 * 24 * 60 * 60,
|
staleRevalidate: 20 * 24 * 60 * 60,
|
||||||
@@ -216,21 +228,21 @@ addon.get("/api/proxy/status", async function (req, res) {
|
|||||||
|
|
||||||
addon.get("/api/image/blur", async function (req, res) {
|
addon.get("/api/image/blur", async function (req, res) {
|
||||||
const imageUrl = req.query.url;
|
const imageUrl = req.query.url;
|
||||||
|
|
||||||
if (!imageUrl) {
|
if (!imageUrl) {
|
||||||
return res.status(400).json({ error: 'Image URL not provided' });
|
return res.status(400).json({ error: 'Image URL not provided' });
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const blurredImageBuffer = await blurImage(imageUrl);
|
const blurredImageBuffer = await blurImage(imageUrl);
|
||||||
|
|
||||||
if (!blurredImageBuffer) {
|
if (!blurredImageBuffer) {
|
||||||
return res.status(500).json({ error: 'Error processing image' });
|
return res.status(500).json({ error: 'Error processing image' });
|
||||||
}
|
}
|
||||||
|
|
||||||
res.setHeader('Content-Type', 'image/jpeg');
|
res.setHeader('Content-Type', 'image/jpeg');
|
||||||
res.setHeader('Cache-Control', 'public, max-age=31536000');
|
res.setHeader('Cache-Control', 'public, max-age=31536000');
|
||||||
|
|
||||||
res.send(blurredImageBuffer);
|
res.send(blurredImageBuffer);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error in blur route:', error);
|
console.error('Error in blur route:', error);
|
||||||
|
|||||||
+98
-26
@@ -29,20 +29,40 @@ async function getCachedImdbRating(imdbId, type) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Helper functions
|
// Helper functions
|
||||||
const getCacheKey = (type, language, tmdbId, rpdbkey, showAgeRatingInGenres = true) =>
|
const getCacheKey = (
|
||||||
`${type}-${language}-${tmdbId}-${rpdbkey}-ageRating:${showAgeRatingInGenres}`;
|
type,
|
||||||
|
language,
|
||||||
|
tmdbId,
|
||||||
|
rpdbkey,
|
||||||
|
enableAgeRating = false,
|
||||||
|
showAgeRatingInGenres = true,
|
||||||
|
showAgeRatingWithImdbRating = false
|
||||||
|
) =>
|
||||||
|
`${type}-${language}-${tmdbId}-${rpdbkey}-ageRating:${enableAgeRating}-${showAgeRatingInGenres}-${showAgeRatingWithImdbRating}`;
|
||||||
|
|
||||||
const processLogo = (logo) => {
|
const processLogo = (logo) => {
|
||||||
if (!logo || blacklistLogoUrls.includes(logo)) return null;
|
if (!logo || blacklistLogoUrls.includes(logo)) return null;
|
||||||
return logo.replace("http://", "https://");
|
return logo.replace("http://", "https://");
|
||||||
};
|
};
|
||||||
|
|
||||||
const buildLinks = (imdbRating, imdbId, title, type, genres, credits, language, castCount, ageRating = null, showAgeRatingInGenres = true) => [
|
const buildLinks = (
|
||||||
Utils.parseImdbLink(imdbRating, imdbId),
|
imdbRating,
|
||||||
Utils.parseShareLink(title, imdbId, type),
|
imdbId,
|
||||||
...Utils.parseGenreLink(genres, type, language, imdbId, ageRating, showAgeRatingInGenres),
|
title,
|
||||||
...Utils.parseCreditsLink(credits, castCount)
|
type,
|
||||||
];
|
genres,
|
||||||
|
credits,
|
||||||
|
language,
|
||||||
|
castCount,
|
||||||
|
ageRating = null,
|
||||||
|
showAgeRatingInGenres = true,
|
||||||
|
showAgeRatingWithImdbRating = false
|
||||||
|
) => [
|
||||||
|
Utils.parseImdbLink(imdbRating, imdbId, ageRating, showAgeRatingWithImdbRating),
|
||||||
|
Utils.parseShareLink(title, imdbId, type),
|
||||||
|
...Utils.parseGenreLink(genres, type, language, imdbId, ageRating, showAgeRatingInGenres),
|
||||||
|
...Utils.parseCreditsLink(credits, castCount)
|
||||||
|
];
|
||||||
|
|
||||||
// Helper function to add age rating to genres
|
// Helper function to add age rating to genres
|
||||||
const addAgeRatingToGenres = (ageRating, genres, showAgeRatingInGenres = true) => {
|
const addAgeRatingToGenres = (ageRating, genres, showAgeRatingInGenres = true) => {
|
||||||
@@ -60,6 +80,10 @@ const fetchMovieData = async (tmdbId, language) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const buildMovieResponse = async (res, type, language, tmdbId, rpdbkey, config = {}) => {
|
const buildMovieResponse = async (res, type, language, tmdbId, rpdbkey, config = {}) => {
|
||||||
|
const enableAgeRating = config.enableAgeRating === true || config.enableAgeRating === "true";
|
||||||
|
const showAgeRatingInGenres = config.showAgeRatingInGenres !== false && config.showAgeRatingInGenres !== "false";
|
||||||
|
const showAgeRatingWithImdbRating = config.showAgeRatingWithImdbRating === true || config.showAgeRatingWithImdbRating === "true";
|
||||||
|
|
||||||
const [poster, logo, imdbRatingRaw, ageRating] = await Promise.all([
|
const [poster, logo, imdbRatingRaw, ageRating] = await Promise.all([
|
||||||
Utils.parsePoster(type, tmdbId, res.poster_path, language, rpdbkey),
|
Utils.parsePoster(type, tmdbId, res.poster_path, language, rpdbkey),
|
||||||
getLogo(tmdbId, language, res.original_language).catch(e => {
|
getLogo(tmdbId, language, res.original_language).catch(e => {
|
||||||
@@ -67,10 +91,10 @@ const buildMovieResponse = async (res, type, language, tmdbId, rpdbkey, config =
|
|||||||
return null;
|
return null;
|
||||||
}),
|
}),
|
||||||
getCachedImdbRating(res.external_ids?.imdb_id, type),
|
getCachedImdbRating(res.external_ids?.imdb_id, type),
|
||||||
getCachedAgeRating(tmdbId, type, language).catch(e => {
|
enableAgeRating ? getCachedAgeRating(tmdbId, type, language).catch(e => {
|
||||||
console.warn(`Error fetching age rating for movie ${tmdbId}:`, e.message);
|
console.warn(`Error fetching age rating for movie ${tmdbId}:`, e.message);
|
||||||
return null;
|
return null;
|
||||||
}),
|
}) : Promise.resolve(null),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const imdbRating = imdbRatingRaw || res.vote_average?.toFixed(1) || "N/A";
|
const imdbRating = imdbRatingRaw || res.vote_average?.toFixed(1) || "N/A";
|
||||||
@@ -79,14 +103,14 @@ const buildMovieResponse = async (res, type, language, tmdbId, rpdbkey, config =
|
|||||||
const hideInCinemaTag = config.hideInCinemaTag === true || config.hideInCinemaTag === "true";
|
const hideInCinemaTag = config.hideInCinemaTag === true || config.hideInCinemaTag === "true";
|
||||||
|
|
||||||
const parsedGenres = Utils.parseGenres(res.genres);
|
const parsedGenres = Utils.parseGenres(res.genres);
|
||||||
const showAgeRatingInGenres = config.showAgeRatingInGenres !== false; // Default to true
|
const resolvedAgeRating = enableAgeRating ? ageRating : null;
|
||||||
|
|
||||||
const response = {
|
const response = {
|
||||||
imdb_id: res.imdb_id,
|
imdb_id: res.imdb_id,
|
||||||
country: Utils.parseCoutry(res.production_countries),
|
country: Utils.parseCoutry(res.production_countries),
|
||||||
description: res.overview,
|
description: res.overview,
|
||||||
director: Utils.parseDirector(res.credits),
|
director: Utils.parseDirector(res.credits),
|
||||||
genre: addAgeRatingToGenres(ageRating, parsedGenres, showAgeRatingInGenres),
|
genre: addAgeRatingToGenres(resolvedAgeRating, parsedGenres, showAgeRatingInGenres),
|
||||||
imdbRating,
|
imdbRating,
|
||||||
name: res.title,
|
name: res.title,
|
||||||
released: new Date(res.release_date),
|
released: new Date(res.release_date),
|
||||||
@@ -99,11 +123,23 @@ const buildMovieResponse = async (res, type, language, tmdbId, rpdbkey, config =
|
|||||||
poster,
|
poster,
|
||||||
runtime: Utils.parseRunTime(res.runtime),
|
runtime: Utils.parseRunTime(res.runtime),
|
||||||
id: returnImdbId ? res.imdb_id : `tmdb:${tmdbId}`,
|
id: returnImdbId ? res.imdb_id : `tmdb:${tmdbId}`,
|
||||||
genres: addAgeRatingToGenres(ageRating, parsedGenres, showAgeRatingInGenres),
|
genres: addAgeRatingToGenres(resolvedAgeRating, parsedGenres, showAgeRatingInGenres),
|
||||||
ageRating,
|
ageRating: resolvedAgeRating,
|
||||||
releaseInfo: res.release_date ? res.release_date.substr(0, 4) : "",
|
releaseInfo: res.release_date ? res.release_date.substr(0, 4) : "",
|
||||||
trailerStreams: Utils.parseTrailerStream(res.videos),
|
trailerStreams: Utils.parseTrailerStream(res.videos),
|
||||||
links: buildLinks(imdbRating, res.imdb_id, res.title, type, res.genres, res.credits, language, castCount, ageRating, showAgeRatingInGenres),
|
links: buildLinks(
|
||||||
|
imdbRating,
|
||||||
|
res.imdb_id,
|
||||||
|
res.title,
|
||||||
|
type,
|
||||||
|
res.genres,
|
||||||
|
res.credits,
|
||||||
|
language,
|
||||||
|
castCount,
|
||||||
|
resolvedAgeRating,
|
||||||
|
showAgeRatingInGenres,
|
||||||
|
showAgeRatingWithImdbRating
|
||||||
|
),
|
||||||
behaviorHints: {
|
behaviorHints: {
|
||||||
defaultVideoId: res.imdb_id ? res.imdb_id : `tmdb:${res.id}`,
|
defaultVideoId: res.imdb_id ? res.imdb_id : `tmdb:${res.id}`,
|
||||||
hasScheduledVideos: false
|
hasScheduledVideos: false
|
||||||
@@ -128,6 +164,9 @@ const fetchTvData = async (tmdbId, language) => {
|
|||||||
|
|
||||||
const buildTvResponse = async (res, type, language, tmdbId, rpdbkey, config = {}) => {
|
const buildTvResponse = async (res, type, language, tmdbId, rpdbkey, config = {}) => {
|
||||||
const runtime = res.episode_run_time?.[0] ?? res.last_episode_to_air?.runtime ?? res.next_episode_to_air?.runtime ?? null;
|
const runtime = res.episode_run_time?.[0] ?? res.last_episode_to_air?.runtime ?? res.next_episode_to_air?.runtime ?? null;
|
||||||
|
const enableAgeRating = config.enableAgeRating === true || config.enableAgeRating === "true";
|
||||||
|
const showAgeRatingInGenres = config.showAgeRatingInGenres !== false && config.showAgeRatingInGenres !== "false";
|
||||||
|
const showAgeRatingWithImdbRating = config.showAgeRatingWithImdbRating === true || config.showAgeRatingWithImdbRating === "true";
|
||||||
|
|
||||||
const [poster, logo, imdbRatingRaw, episodes, ageRating] = await Promise.all([
|
const [poster, logo, imdbRatingRaw, episodes, ageRating] = await Promise.all([
|
||||||
Utils.parsePoster(type, tmdbId, res.poster_path, language, rpdbkey),
|
Utils.parsePoster(type, tmdbId, res.poster_path, language, rpdbkey),
|
||||||
@@ -142,10 +181,10 @@ const buildTvResponse = async (res, type, language, tmdbId, rpdbkey, config = {}
|
|||||||
console.warn(`Error fetching episodes for series ${tmdbId}:`, e.message);
|
console.warn(`Error fetching episodes for series ${tmdbId}:`, e.message);
|
||||||
return [];
|
return [];
|
||||||
}),
|
}),
|
||||||
getCachedAgeRating(tmdbId, type, language).catch(e => {
|
enableAgeRating ? getCachedAgeRating(tmdbId, type, language).catch(e => {
|
||||||
console.warn(`Error fetching age rating for series ${tmdbId}:`, e.message);
|
console.warn(`Error fetching age rating for series ${tmdbId}:`, e.message);
|
||||||
return null;
|
return null;
|
||||||
})
|
}) : Promise.resolve(null)
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const imdbRating = imdbRatingRaw || res.vote_average?.toFixed(1) || "N/A";
|
const imdbRating = imdbRatingRaw || res.vote_average?.toFixed(1) || "N/A";
|
||||||
@@ -153,12 +192,12 @@ const buildTvResponse = async (res, type, language, tmdbId, rpdbkey, config = {}
|
|||||||
const returnImdbId = config.returnImdbId === true || config.returnImdbId === "true";
|
const returnImdbId = config.returnImdbId === true || config.returnImdbId === "true";
|
||||||
const hideInCinemaTag = config.hideInCinemaTag === true || config.hideInCinemaTag === "true";
|
const hideInCinemaTag = config.hideInCinemaTag === true || config.hideInCinemaTag === "true";
|
||||||
const parsedGenres = Utils.parseGenres(res.genres);
|
const parsedGenres = Utils.parseGenres(res.genres);
|
||||||
const showAgeRatingInGenres = config.showAgeRatingInGenres !== false; // Default to true
|
const resolvedAgeRating = enableAgeRating ? ageRating : null;
|
||||||
|
|
||||||
const response = {
|
const response = {
|
||||||
country: Utils.parseCoutry(res.production_countries),
|
country: Utils.parseCoutry(res.production_countries),
|
||||||
description: res.overview,
|
description: res.overview,
|
||||||
genre: addAgeRatingToGenres(ageRating, parsedGenres, showAgeRatingInGenres),
|
genre: addAgeRatingToGenres(resolvedAgeRating, parsedGenres, showAgeRatingInGenres),
|
||||||
imdbRating,
|
imdbRating,
|
||||||
imdb_id: res.external_ids.imdb_id,
|
imdb_id: res.external_ids.imdb_id,
|
||||||
name: res.name,
|
name: res.name,
|
||||||
@@ -172,11 +211,23 @@ const buildTvResponse = async (res, type, language, tmdbId, rpdbkey, config = {}
|
|||||||
background: `https://image.tmdb.org/t/p/original${res.backdrop_path}`,
|
background: `https://image.tmdb.org/t/p/original${res.backdrop_path}`,
|
||||||
slug: Utils.parseSlug(type, res.name, res.external_ids.imdb_id),
|
slug: Utils.parseSlug(type, res.name, res.external_ids.imdb_id),
|
||||||
id: returnImdbId ? res.imdb_id : `tmdb:${tmdbId}`,
|
id: returnImdbId ? res.imdb_id : `tmdb:${tmdbId}`,
|
||||||
genres: addAgeRatingToGenres(ageRating, parsedGenres, showAgeRatingInGenres),
|
genres: addAgeRatingToGenres(resolvedAgeRating, parsedGenres, showAgeRatingInGenres),
|
||||||
ageRating,
|
ageRating: resolvedAgeRating,
|
||||||
releaseInfo: Utils.parseYear(res.status, res.first_air_date, res.last_air_date),
|
releaseInfo: Utils.parseYear(res.status, res.first_air_date, res.last_air_date),
|
||||||
videos: episodes || [],
|
videos: episodes || [],
|
||||||
links: buildLinks(imdbRating, res.external_ids.imdb_id, res.name, type, res.genres, res.credits, language, castCount, ageRating, showAgeRatingInGenres),
|
links: buildLinks(
|
||||||
|
imdbRating,
|
||||||
|
res.external_ids.imdb_id,
|
||||||
|
res.name,
|
||||||
|
type,
|
||||||
|
res.genres,
|
||||||
|
res.credits,
|
||||||
|
language,
|
||||||
|
castCount,
|
||||||
|
resolvedAgeRating,
|
||||||
|
showAgeRatingInGenres,
|
||||||
|
showAgeRatingWithImdbRating
|
||||||
|
),
|
||||||
trailers: Utils.parseTrailers(res.videos),
|
trailers: Utils.parseTrailers(res.videos),
|
||||||
trailerStreams: Utils.parseTrailerStream(res.videos),
|
trailerStreams: Utils.parseTrailerStream(res.videos),
|
||||||
behaviorHints: {
|
behaviorHints: {
|
||||||
@@ -206,8 +257,19 @@ const buildTvResponse = async (res, type, language, tmdbId, rpdbkey, config = {}
|
|||||||
|
|
||||||
// Main function
|
// Main function
|
||||||
async function getMeta(type, language, tmdbId, rpdbkey, config = {}) {
|
async function getMeta(type, language, tmdbId, rpdbkey, config = {}) {
|
||||||
const showAgeRatingInGenres = config.showAgeRatingInGenres !== false; // Default to true
|
const enableAgeRating = config.enableAgeRating === true || config.enableAgeRating === "true";
|
||||||
const cacheKey = getCacheKey(type, language, tmdbId, rpdbkey, showAgeRatingInGenres);
|
const showAgeRatingInGenres = config.showAgeRatingInGenres !== false && config.showAgeRatingInGenres !== "false";
|
||||||
|
const showAgeRatingWithImdbRating = config.showAgeRatingWithImdbRating === true || config.showAgeRatingWithImdbRating === "true";
|
||||||
|
|
||||||
|
const cacheKey = getCacheKey(
|
||||||
|
type,
|
||||||
|
language,
|
||||||
|
tmdbId,
|
||||||
|
rpdbkey,
|
||||||
|
enableAgeRating,
|
||||||
|
showAgeRatingInGenres,
|
||||||
|
showAgeRatingWithImdbRating
|
||||||
|
);
|
||||||
const cachedData = cache.get(cacheKey);
|
const cachedData = cache.get(cacheKey);
|
||||||
|
|
||||||
if (cachedData && (Date.now() - cachedData.timestamp) < CACHE_TTL) {
|
if (cachedData && (Date.now() - cachedData.timestamp) < CACHE_TTL) {
|
||||||
@@ -216,8 +278,18 @@ async function getMeta(type, language, tmdbId, rpdbkey, config = {}) {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const meta = await (type === "movie" ?
|
const meta = await (type === "movie" ?
|
||||||
fetchMovieData(tmdbId, language).then(res => buildMovieResponse(res, type, language, tmdbId, rpdbkey, config)) :
|
fetchMovieData(tmdbId, language).then(res => buildMovieResponse(res, type, language, tmdbId, rpdbkey, {
|
||||||
fetchTvData(tmdbId, language).then(res => buildTvResponse(res, type, language, tmdbId, rpdbkey, config))
|
...config,
|
||||||
|
enableAgeRating,
|
||||||
|
showAgeRatingInGenres,
|
||||||
|
showAgeRatingWithImdbRating
|
||||||
|
})) :
|
||||||
|
fetchTvData(tmdbId, language).then(res => buildTvResponse(res, type, language, tmdbId, rpdbkey, {
|
||||||
|
...config,
|
||||||
|
enableAgeRating,
|
||||||
|
showAgeRatingInGenres,
|
||||||
|
showAgeRatingWithImdbRating
|
||||||
|
}))
|
||||||
);
|
);
|
||||||
|
|
||||||
cache.set(cacheKey, { data: meta, timestamp: Date.now() });
|
cache.set(cacheKey, { data: meta, timestamp: Date.now() });
|
||||||
|
|||||||
@@ -71,9 +71,9 @@ function parseTrailerStream(videos) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseImdbLink(vote_average, imdb_id) {
|
function parseImdbLink(vote_average, imdb_id, ageRating = null, showAgeRatingWithImdbRating = false) {
|
||||||
return {
|
return {
|
||||||
name: vote_average,
|
name: showAgeRatingWithImdbRating && ageRating ? `${ageRating}\u2003\u2003${vote_average}` : vote_average,
|
||||||
category: "imdb",
|
category: "imdb",
|
||||||
url: `https://imdb.com/title/${imdb_id}`,
|
url: `https://imdb.com/title/${imdb_id}`,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -2,17 +2,56 @@ import { Switch } from "@/components/ui/switch";
|
|||||||
import { useConfig } from "@/contexts/ConfigContext";
|
import { useConfig } from "@/contexts/ConfigContext";
|
||||||
|
|
||||||
export function AgeRatingDisplayToggle() {
|
export function AgeRatingDisplayToggle() {
|
||||||
const { showAgeRatingInGenres, setShowAgeRatingInGenres } = useConfig();
|
const {
|
||||||
|
enableAgeRating,
|
||||||
|
showAgeRatingInGenres,
|
||||||
|
showAgeRatingWithImdbRating,
|
||||||
|
setEnableAgeRating,
|
||||||
|
setShowAgeRatingInGenres,
|
||||||
|
setShowAgeRatingWithImdbRating
|
||||||
|
} = useConfig();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<div className="flex flex-col gap-4">
|
||||||
<div className="space-y-0.5">
|
<div className="flex items-center justify-between">
|
||||||
<h1 className="text-sm font-semibold mb-1">Display Age Rating</h1>
|
<div className="space-y-0.5">
|
||||||
<p className="text-gray-500 text-sm">
|
<h1 className="text-sm font-semibold mb-1">Enable Age Rating</h1>
|
||||||
Display age rating as first genre
|
<p className="text-gray-500 text-sm">
|
||||||
</p>
|
Fetch and attach the content rating to metadata
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<Switch checked={enableAgeRating} onCheckedChange={setEnableAgeRating} />
|
||||||
</div>
|
</div>
|
||||||
<Switch checked={showAgeRatingInGenres} onCheckedChange={setShowAgeRatingInGenres} />
|
|
||||||
</>
|
<div className={`grid gap-4 transition-opacity ${enableAgeRating ? "opacity-100" : "opacity-40"}`}>
|
||||||
|
<div className="flex items-center justify-between">
|
||||||
|
<div className="space-y-0.5">
|
||||||
|
<h2 className="text-sm font-semibold mb-1">Show in Genres</h2>
|
||||||
|
<p className="text-gray-500 text-sm">
|
||||||
|
Insert the age rating as the first genre entry
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<Switch
|
||||||
|
checked={showAgeRatingInGenres}
|
||||||
|
onCheckedChange={setShowAgeRatingInGenres}
|
||||||
|
disabled={!enableAgeRating}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex items-center justify-between">
|
||||||
|
<div className="space-y-0.5">
|
||||||
|
<h2 className="text-sm font-semibold mb-1">Show with IMDb Rating</h2>
|
||||||
|
<p className="text-gray-500 text-sm">
|
||||||
|
Append the age rating next to the IMDb score
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<Switch
|
||||||
|
checked={showAgeRatingWithImdbRating}
|
||||||
|
onCheckedChange={setShowAgeRatingWithImdbRating}
|
||||||
|
disabled={!enableAgeRating}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,6 +31,8 @@ export function ConfigProvider({ children }: { children: React.ReactNode }) {
|
|||||||
const [hideInCinemaTag, setHideInCinemaTag] = useState(false);
|
const [hideInCinemaTag, setHideInCinemaTag] = useState(false);
|
||||||
const [castCount, setCastCount] = useState<number | undefined>(5);
|
const [castCount, setCastCount] = useState<number | undefined>(5);
|
||||||
const [showAgeRatingInGenres, setShowAgeRatingInGenres] = useState(true);
|
const [showAgeRatingInGenres, setShowAgeRatingInGenres] = useState(true);
|
||||||
|
const [enableAgeRating, setEnableAgeRating] = useState(false);
|
||||||
|
const [showAgeRatingWithImdbRating, setShowAgeRatingWithImdbRating] = useState(false);
|
||||||
|
|
||||||
const loadDefaultCatalogs = () => {
|
const loadDefaultCatalogs = () => {
|
||||||
const defaultCatalogs = baseCatalogs.map(catalog => ({
|
const defaultCatalogs = baseCatalogs.map(catalog => ({
|
||||||
@@ -60,7 +62,9 @@ export function ConfigProvider({ children }: { children: React.ReactNode }) {
|
|||||||
if (config.language) setLanguage(config.language);
|
if (config.language) setLanguage(config.language);
|
||||||
if (config.hideInCinemaTag) setHideInCinemaTag(config.hideInCinemaTag === "true" || config.hideInCinemaTag === true);
|
if (config.hideInCinemaTag) setHideInCinemaTag(config.hideInCinemaTag === "true" || config.hideInCinemaTag === true);
|
||||||
if (config.castCount !== undefined) setCastCount(config.castCount === "Unlimited" ? undefined : Number(config.castCount));
|
if (config.castCount !== undefined) setCastCount(config.castCount === "Unlimited" ? undefined : Number(config.castCount));
|
||||||
|
if (config.enableAgeRating !== undefined) setEnableAgeRating(config.enableAgeRating === "true" || config.enableAgeRating === true);
|
||||||
if (config.showAgeRatingInGenres !== undefined) setShowAgeRatingInGenres(config.showAgeRatingInGenres === "true" || config.showAgeRatingInGenres === true);
|
if (config.showAgeRatingInGenres !== undefined) setShowAgeRatingInGenres(config.showAgeRatingInGenres === "true" || config.showAgeRatingInGenres === true);
|
||||||
|
if (config.showAgeRatingWithImdbRating !== undefined) setShowAgeRatingWithImdbRating(config.showAgeRatingWithImdbRating === "true" || config.showAgeRatingWithImdbRating === true);
|
||||||
|
|
||||||
if (config.catalogs) {
|
if (config.catalogs) {
|
||||||
const catalogsWithNames = config.catalogs.map(catalog => {
|
const catalogsWithNames = config.catalogs.map(catalog => {
|
||||||
@@ -122,6 +126,8 @@ export function ConfigProvider({ children }: { children: React.ReactNode }) {
|
|||||||
hideInCinemaTag,
|
hideInCinemaTag,
|
||||||
castCount,
|
castCount,
|
||||||
showAgeRatingInGenres,
|
showAgeRatingInGenres,
|
||||||
|
enableAgeRating,
|
||||||
|
showAgeRatingWithImdbRating,
|
||||||
setRpdbkey,
|
setRpdbkey,
|
||||||
setGeminiKey,
|
setGeminiKey,
|
||||||
setMdblistkey,
|
setMdblistkey,
|
||||||
@@ -139,6 +145,8 @@ export function ConfigProvider({ children }: { children: React.ReactNode }) {
|
|||||||
setHideInCinemaTag,
|
setHideInCinemaTag,
|
||||||
setCastCount,
|
setCastCount,
|
||||||
setShowAgeRatingInGenres,
|
setShowAgeRatingInGenres,
|
||||||
|
setEnableAgeRating,
|
||||||
|
setShowAgeRatingWithImdbRating,
|
||||||
loadConfigFromUrl
|
loadConfigFromUrl
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -26,6 +26,8 @@ export type ConfigContextType = {
|
|||||||
hideInCinemaTag: boolean;
|
hideInCinemaTag: boolean;
|
||||||
castCount: number | undefined;
|
castCount: number | undefined;
|
||||||
showAgeRatingInGenres: boolean;
|
showAgeRatingInGenres: boolean;
|
||||||
|
enableAgeRating: boolean;
|
||||||
|
showAgeRatingWithImdbRating: boolean;
|
||||||
setRpdbkey: (rpdbkey: string) => void;
|
setRpdbkey: (rpdbkey: string) => void;
|
||||||
setGeminiKey: (geminikey: string) => void;
|
setGeminiKey: (geminikey: string) => void;
|
||||||
setMdblistkey: (mdblistkey: string) => void;
|
setMdblistkey: (mdblistkey: string) => void;
|
||||||
@@ -43,6 +45,8 @@ export type ConfigContextType = {
|
|||||||
setHideInCinemaTag: (hide: boolean) => void;
|
setHideInCinemaTag: (hide: boolean) => void;
|
||||||
setCastCount: (count: number | undefined) => void;
|
setCastCount: (count: number | undefined) => void;
|
||||||
setShowAgeRatingInGenres: (show: boolean) => void;
|
setShowAgeRatingInGenres: (show: boolean) => void;
|
||||||
|
setEnableAgeRating: (enable: boolean) => void;
|
||||||
|
setShowAgeRatingWithImdbRating: (show: boolean) => void;
|
||||||
loadConfigFromUrl: () => void;
|
loadConfigFromUrl: () => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -22,6 +22,8 @@ interface AddonConfig {
|
|||||||
hideInCinemaTag?: boolean;
|
hideInCinemaTag?: boolean;
|
||||||
castCount?: number;
|
castCount?: number;
|
||||||
showAgeRatingInGenres?: boolean;
|
showAgeRatingInGenres?: boolean;
|
||||||
|
enableAgeRating?: boolean;
|
||||||
|
showAgeRatingWithImdbRating?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function generateAddonUrl(config: AddonConfig): string {
|
export function generateAddonUrl(config: AddonConfig): string {
|
||||||
@@ -47,7 +49,9 @@ export function generateAddonUrl(config: AddonConfig): string {
|
|||||||
searchEnabled: config.searchEnabled === false ? "false" : undefined,
|
searchEnabled: config.searchEnabled === false ? "false" : undefined,
|
||||||
hideInCinemaTag: config.hideInCinemaTag === true ? "true" : undefined,
|
hideInCinemaTag: config.hideInCinemaTag === true ? "true" : undefined,
|
||||||
castCount: typeof config.castCount === "number" ? config.castCount : undefined,
|
castCount: typeof config.castCount === "number" ? config.castCount : undefined,
|
||||||
showAgeRatingInGenres: config.showAgeRatingInGenres === true ? "true" : undefined,
|
enableAgeRating: typeof config.enableAgeRating === "boolean" ? String(config.enableAgeRating) : undefined,
|
||||||
|
showAgeRatingInGenres: typeof config.showAgeRatingInGenres === "boolean" ? String(config.showAgeRatingInGenres) : undefined,
|
||||||
|
showAgeRatingWithImdbRating: typeof config.showAgeRatingWithImdbRating === "boolean" ? String(config.showAgeRatingWithImdbRating) : undefined,
|
||||||
};
|
};
|
||||||
|
|
||||||
const cleanConfig = Object.fromEntries(
|
const cleanConfig = Object.fromEntries(
|
||||||
|
|||||||
@@ -107,7 +107,7 @@ const Others = () => {
|
|||||||
<Card className="p-6">
|
<Card className="p-6">
|
||||||
<AgeRatingSelect />
|
<AgeRatingSelect />
|
||||||
</Card>
|
</Card>
|
||||||
<Card className="flex flex-row items-center justify-between p-6">
|
<Card className="p-6">
|
||||||
<AgeRatingDisplayToggle />
|
<AgeRatingDisplayToggle />
|
||||||
</Card>
|
</Card>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user