aboutsummaryrefslogtreecommitdiff
path: root/pages/api/v2/episode
diff options
context:
space:
mode:
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) {