diff options
Diffstat (limited to 'pages/api/v2/episode')
| -rw-r--r-- | pages/api/v2/episode/[id].tsx (renamed from pages/api/v2/episode/[id].js) | 128 |
1 files changed, 82 insertions, 46 deletions
diff --git a/pages/api/v2/episode/[id].js b/pages/api/v2/episode/[id].tsx index b601f62..b646126 100644 --- a/pages/api/v2/episode/[id].js +++ b/pages/api/v2/episode/[id].tsx @@ -1,17 +1,21 @@ +// @ts-nocheck + import axios from "axios"; import { rateLimiterRedis, rateSuperStrict, redis } from "@/lib/redis"; import appendMetaToEpisodes from "@/utils/appendMetaToEpisodes"; +import { NextApiRequest, NextApiResponse } from "next"; +import { AnifyEpisode, ConsumetInfo, EpisodeData } from "types"; +import { Episode } from "@/types/api/Episode"; +import { getProviderWithMostEpisodesAndImage } from "@/utils/parseMetaData"; -let CONSUMET_URI; +let CONSUMET_URI: string | null; CONSUMET_URI = process.env.API_URI || null; if (CONSUMET_URI && CONSUMET_URI.endsWith("/")) { CONSUMET_URI = CONSUMET_URI.slice(0, -1); } -const API_KEY = process.env.API_KEY; - -const isAscending = (data) => { +const isAscending = (data: Episode[]) => { for (let i = 1; i < data.length; i++) { if (data[i].number < data[i - 1].number) { return false; @@ -20,7 +24,16 @@ const isAscending = (data) => { return true; }; -function filterData(data, type) { +export interface RawEpisodeData { + map?: boolean; + providerId: string; + episodes: { + sub: Episode[]; + dub: Episode[]; + }; +} + +function filterData(data: RawEpisodeData[], type: "sub" | "dub") { // Filter the data based on the type (sub or dub) and providerId const filteredData = data.map((item) => { if (item?.map === true) { @@ -44,10 +57,10 @@ function filterData(data, type) { return noEmpty; } -async function fetchConsumet(id) { +async function fetchConsumet(id?: string | string[] | undefined) { try { - async function fetchData(dub) { - const { data } = await axios.get( + const fetchData = async (dub?: any) => { + const { data } = await axios.get<ConsumetInfo>( `${CONSUMET_URI}/meta/anilist/info/${id}${dub ? "?dub=true" : ""}` ); if (data?.message === "Anime not found" && data?.length < 1) { @@ -59,23 +72,32 @@ async function fetchConsumet(id) { } const reformatted = data.episodes?.map((item) => ({ - id: item?.id || null, + id: item.id, title: item?.title || null, img: item?.image || null, number: item?.number || null, - createdAt: item?.createdAt || null, + createdAt: item?.airDate || null, description: item?.description || null, - url: item?.url || null, })); return reformatted; - } + }; const [subData, dubData] = await Promise.all([ fetchData(), fetchData(true), ]); + if (subData.every((i) => i.id?.includes("dub"))) { + // replace dub in title with sub + subData.forEach((item) => { + if (item.id?.includes("dub")) { + item.id = item.id?.replace("dub", "anime"); + } + }); + console.log("replaced dub with sub"); + } + const array = [ { map: true, @@ -88,38 +110,34 @@ async function fetchConsumet(id) { ]; return array; - } catch (error) { + } catch (error: any) { console.error("Error fetching and processing data:", error.message); return []; } } -async function fetchAnify(id) { +async function fetchAnify(id?: string) { try { - const { data } = await axios.get(`https://api.anify.tv/episodes/${id}`); + const { data } = await axios.get<AnifyEpisode[]>( + `https://api.anify.tv/episodes/${id}` + ); if (!data) { return []; } - const filtered = data.filter((item) => item.providerId !== "kass"); - // const modifiedData = filtered.map((provider) => { - // if (provider.providerId === "gogoanime") { - // const reversedEpisodes = [...provider.episodes].reverse(); - // return { ...provider, episodes: reversedEpisodes }; - // } - // return provider; - // }); + const filtered = data.filter( + (item) => item.providerId !== "9anime" && item.providerId !== "kass" + ); - // return modifiedData; return filtered; - } catch (error) { + } catch (error: any) { console.error("Error fetching and processing data:", error.message); return []; } } -async function fetchCoverImage(id, available = false) { +async function fetchCoverImage(id: string, available = false) { try { if (!process.env.API_KEY) { return []; @@ -137,16 +155,20 @@ async function fetchCoverImage(id, available = false) { return []; } - const getData = data[0].data; + const getData = getProviderWithMostEpisodesAndImage(data); + // const getData = data?.[0]?.data; - return getData; - } catch (error) { + return getData.data; + } catch (error: any) { console.error("Error fetching and processing data:", error.message); return []; } } -export default async function handler(req, res) { +export default async function handler( + req: NextApiRequest, + res: NextApiResponse +) { const { id, releasing = "false", dub = false, refresh = null } = req.query; // if releasing is true then cache for 1 hour, if it false cache for 1 month; @@ -159,11 +181,11 @@ export default async function handler(req, res) { let cached; let meta; - let headers; + let headers: any = {}; if (redis) { try { - const ipAddress = req.socket.remoteAddress; + const ipAddress: any = req.socket.remoteAddress; refresh ? await rateSuperStrict.consume(ipAddress) : await rateLimiterRedis.consume(ipAddress); @@ -171,9 +193,7 @@ export default async function handler(req, res) { headers = refresh ? await rateSuperStrict.get(ipAddress) : await rateLimiterRedis.get(ipAddress); - - console.log(headers); - } catch (error) { + } catch (error: any) { return res.status(429).json({ error: `Too Many Requests, retry after ${getTimeFromMs( error.msBeforeNext @@ -182,20 +202,28 @@ export default async function handler(req, res) { }); } + meta = await redis.get(`meta:${id}`); + const parsedMeta = JSON.parse(meta); + if (parsedMeta?.length === 0) { + await redis.del(`meta:${id}`); + console.log("deleted meta cache"); + meta = null; + } + if (refresh) { await redis.del(`episode:${id}`); - console.log("deleted cache"); } else { cached = await redis.get(`episode:${id}`); - console.log("using redis"); + if (cached?.length === 0) { + await redis.del(`episode:${id}`); + cached = null; + } } - - meta = await redis.get(`meta:${id}`); } if (cached && !refresh) { if (dub) { - const filteredData = filterData(JSON.parse(cached), "dub"); + const filteredData: EpisodeData[] = filterData(JSON.parse(cached), "dub"); let filtered = filteredData.filter((item) => item?.episodes?.some((epi) => epi.hasDub !== false) @@ -208,7 +236,9 @@ export default async function handler(req, res) { res.setHeader("X-RateLimit-Remaining", headers.remainingPoints); res.setHeader("X-RateLimit-BeforeReset", headers.msBeforeNext); - return res.status(200).json(filtered); + return res + .status(200) + .json(filtered?.filter((i) => i?.providerId !== "9anime")); } else { const filteredData = filterData(JSON.parse(cached), "sub"); @@ -221,11 +251,13 @@ export default async function handler(req, res) { res.setHeader("X-RateLimit-Remaining", headers.remainingPoints); res.setHeader("X-RateLimit-BeforeReset", headers.msBeforeNext); - return res.status(200).send(filtered); + return res + .status(200) + .send(filtered?.filter((i) => i?.providerId !== "9anime")); } } else { const [consumet, anify, cover] = await Promise.all([ - fetchConsumet(id, dub), + fetchConsumet(id), fetchAnify(id), fetchCoverImage(id, meta), ]); @@ -249,12 +281,16 @@ export default async function handler(req, res) { if (meta) { data = await appendMetaToEpisodes(filteredData, JSON.parse(meta)); - } else if (cover && !cover.some((e) => e.img === null)) { + } else if ( + cover && + // !cover?.some((item: { img: null }) => item.img === null) && + cover?.length > 0 + ) { if (redis) await redis.set(`meta:${id}`, JSON.stringify(cover)); data = await appendMetaToEpisodes(filteredData, cover); } - if (redis && cacheTime !== null) { + if (redis && cacheTime !== null && rawData?.length > 0) { await redis.set( `episode:${id}`, JSON.stringify(rawData), @@ -282,7 +318,7 @@ export default async function handler(req, res) { } } -function getTimeFromMs(time) { +function getTimeFromMs(time: number) { const timeInSeconds = time / 1000; if (timeInSeconds >= 3600) { |