diff options
Diffstat (limited to 'pages/api')
| -rw-r--r-- | pages/api/v2/admin/broadcast/index.js | 54 | ||||
| -rw-r--r-- | pages/api/v2/admin/bug-report/index.js | 30 | ||||
| -rw-r--r-- | pages/api/v2/episode/[id].js | 171 | ||||
| -rw-r--r-- | pages/api/v2/etc/recent/[page].js | 6 | ||||
| -rw-r--r-- | pages/api/v2/info/[id].js | 47 | ||||
| -rw-r--r-- | pages/api/v2/info/index.js | 60 | ||||
| -rw-r--r-- | pages/api/v2/pages/[...id].js | 34 | ||||
| -rw-r--r-- | pages/api/v2/source/index.js | 8 |
8 files changed, 287 insertions, 123 deletions
diff --git a/pages/api/v2/admin/broadcast/index.js b/pages/api/v2/admin/broadcast/index.js index d3d3af0..470d61d 100644 --- a/pages/api/v2/admin/broadcast/index.js +++ b/pages/api/v2/admin/broadcast/index.js @@ -1,9 +1,17 @@ import { rateLimitStrict, redis } from "@/lib/redis"; -// import { getServerSession } from "next-auth"; -// import { authOptions } from "pages/api/auth/[...nextauth]"; +import { getServerSession } from "next-auth"; +import { authOptions } from "pages/api/auth/[...nextauth]"; export default async function handler(req, res) { // Check if the custom header "X-Your-Custom-Header" is present and has a specific value + const sessions = await getServerSession(req, res, authOptions); + + const admin = sessions?.user?.name === process.env.ADMIN_USERNAME; + // if req.method === POST and admin === false return 401 + if (!admin && req.method === "DELETE") { + return res.status(401).json({ message: "Unauthorized" }); + } + const customHeaderValue = req.headers["x-broadcast-key"]; if (customHeaderValue !== "get-broadcast") { @@ -21,14 +29,40 @@ export default async function handler(req, res) { }); } - const getId = await redis.get(`broadcast`); - if (getId) { - const broadcast = JSON.parse(getId); - return res - .status(200) - .json({ message: broadcast.message, startAt: broadcast.startAt }); - } else { - return res.status(200).json({ message: "No broadcast" }); + if (req.method === "POST") { + const { message, startAt = undefined, show = false } = req.body; + if (!message) { + return res.status(400).json({ message: "Message is required" }); + } + + const broadcastContent = { + message, + startAt, + show, + }; + await redis.set(`broadcasts`, JSON.stringify(broadcastContent)); + return res.status(200).json({ message: "Broadcast created" }); + } else if (req.method === "DELETE") { + const br = await redis.get(`broadcasts`); + // set broadcast show as false + if (br) { + const broadcast = JSON.parse(br); + broadcast.show = false; + await redis.set(`broadcasts`, JSON.stringify(broadcast)); + } + return res.status(200).json({ message: "Broadcast deleted" }); + } else if (req.method === "GET") { + const getId = await redis.get(`broadcasts`); + if (getId) { + const broadcast = JSON.parse(getId); + return res.status(200).json({ + message: broadcast.message, + startAt: broadcast.startAt, + show: broadcast.show, + }); + } else { + return res.status(200).json({ message: "No broadcast" }); + } } } diff --git a/pages/api/v2/admin/bug-report/index.js b/pages/api/v2/admin/bug-report/index.js index fc5ee77..508e6cd 100644 --- a/pages/api/v2/admin/bug-report/index.js +++ b/pages/api/v2/admin/bug-report/index.js @@ -8,16 +8,6 @@ export default async function handler(req, res) { // create random id each time the endpoint is called const id = Math.random().toString(36).substr(2, 9); - // if (!admin) { - // return res.status(401).json({ message: "Unauthorized" }); - // } - const { data } = req.body; - - // if method is not POST return message "Method not allowed" - if (req.method !== "POST") { - return res.status(405).json({ message: "Method not allowed" }); - } - try { if (redis) { try { @@ -29,16 +19,22 @@ export default async function handler(req, res) { }); } - const getId = await redis.get(`report:${id}`); - if (getId) { + if (req.method === "POST") { + const { data } = req.body; + + data.id = id; + + await redis.set(`report:${id}`, JSON.stringify(data)); return res .status(200) - .json({ message: `Data already exist for id: ${id}` }); + .json({ message: `Report has successfully sent, with Id of ${id}` }); + } else if (req.method === "DELETE") { + const { reportId } = req.body; + await redis.del(`report:${reportId}`); + return res.status(200).json({ message: `Report has been deleted` }); + } else { + return res.status(405).json({ message: "Method not allowed" }); } - await redis.set(`report:${id}`, JSON.stringify(data)); - return res - .status(200) - .json({ message: `Report has successfully sent, with Id of ${id}` }); } return res.status(200).json({ message: "redis is not defined" }); diff --git a/pages/api/v2/episode/[id].js b/pages/api/v2/episode/[id].js index c1fac8b..3f1372b 100644 --- a/pages/api/v2/episode/[id].js +++ b/pages/api/v2/episode/[id].js @@ -3,7 +3,13 @@ import { rateLimitStrict, rateLimiterRedis, redis } from "@/lib/redis"; import appendImagesToEpisodes from "@/utils/combineImages"; import appendMetaToEpisodes from "@/utils/appendMetaToEpisodes"; -const CONSUMET_URI = process.env.API_URI; +let CONSUMET_URI; + +CONSUMET_URI = process.env.API_URI; +if (CONSUMET_URI.endsWith("/")) { + CONSUMET_URI = CONSUMET_URI.slice(0, -1); +} + const API_KEY = process.env.API_KEY; const isAscending = (data) => { @@ -15,37 +21,70 @@ const isAscending = (data) => { return true; }; -async function fetchConsumet(id, dub) { - try { - if (dub) { - return []; +function filterData(data, type) { + // Filter the data based on the type (sub or dub) and providerId + const filteredData = data.map((item) => { + if (item?.map === true) { + if (item.episodes[type].length === 0) { + return null; + } else { + return { + ...item, + episodes: Object?.entries(item.episodes[type]).map( + ([id, episode]) => ({ + ...episode, + }) + ), + }; + } } + return item; + }); - const { data } = await axios.get( - `${CONSUMET_URI}/meta/anilist/episodes/${id}` - ); + const noEmpty = filteredData.filter((i) => i !== null); + return noEmpty; +} - if (data?.message === "Anime not found" && data?.length < 1) { - return []; +async function fetchConsumet(id) { + try { + async function fetchData(dub) { + const { data } = await axios.get( + `${CONSUMET_URI}/meta/anilist/episodes/${id}${dub ? "?dub=true" : ""}` + ); + if (data?.message === "Anime not found" && data?.length < 1) { + return []; + } + + if (dub) { + if (!data?.some((i) => i.id.includes("dub"))) return []; + } + + const reformatted = data.map((item) => ({ + id: item?.id || null, + title: item?.title || null, + img: item?.image || null, + number: item?.number || null, + createdAt: item?.createdAt || null, + description: item?.description || null, + url: item?.url || null, + })); + + return reformatted; } - const reformatted = data.map((item) => ({ - id: item?.id || null, - title: item?.title || null, - img: item?.image || null, - number: item?.number || null, - createdAt: item?.createdAt || null, - description: item?.description || null, - url: item?.url || null, - })); + const [subData, dubData] = await Promise.all([ + fetchData(), + fetchData(true), + ]); const array = [ { map: true, providerId: "gogoanime", - episodes: isAscending(reformatted) - ? reformatted - : reformatted.reverse(), + episodes: { + sub: isAscending(subData) ? subData : subData.reverse(), + dub: isAscending(dubData) ? dubData : dubData.reverse(), + }, }, ]; @@ -73,7 +112,15 @@ async function fetchAnify(id) { const filtered = data.filter( (item) => item.providerId !== "animepahe" && item.providerId !== "kass" ); - + // const modifiedData = filtered.map((provider) => { + // if (provider.providerId === "gogoanime") { + // const reversedEpisodes = [...provider.episodes].reverse(); + // return { ...provider, episodes: reversedEpisodes }; + // } + // return provider; + // }); + + // return modifiedData; return filtered; } catch (error) { console.error("Error fetching and processing data:", error.message); @@ -81,12 +128,16 @@ async function fetchAnify(id) { } } -async function fetchCoverImage(id) { +async function fetchCoverImage(id, available = false) { try { if (!process.env.API_KEY) { return []; } + if (available) { + return null; + } + const { data } = await axios.get( `https://api.anify.tv/content-metadata/${id}?apikey=${API_KEY}` ); @@ -95,7 +146,9 @@ async function fetchCoverImage(id) { return []; } - return data; + const getData = data[0].data; + + return getData; } catch (error) { console.error("Error fetching and processing data:", error.message); return []; @@ -124,10 +177,10 @@ export default async function handler(req, res) { } if (refresh) { - await redis.del(id); + await redis.del(`episode:${id}`); console.log("deleted cache"); } else { - cached = await redis.get(id); + cached = await redis.get(`episode:${id}`); console.log("using redis"); } @@ -136,49 +189,75 @@ export default async function handler(req, res) { if (cached && !refresh) { if (dub) { - const filtered = JSON.parse(cached).filter((item) => - item.episodes.some((epi) => epi.hasDub === true) + const filteredData = filterData(JSON.parse(cached), "dub"); + + let filtered = filteredData.filter((item) => + item?.episodes?.some((epi) => epi.hasDub !== false) ); + + if (meta) { + filtered = await appendMetaToEpisodes(filtered, JSON.parse(meta)); + } + return res.status(200).json(filtered); } else { - return res.status(200).json(JSON.parse(cached)); + const filteredData = filterData(JSON.parse(cached), "sub"); + + let filtered = filteredData; + + if (meta) { + filtered = await appendMetaToEpisodes(filteredData, JSON.parse(meta)); + } + + return res.status(200).json(filtered); } } else { const [consumet, anify, cover] = await Promise.all([ fetchConsumet(id, dub), fetchAnify(id), - fetchCoverImage(id), + fetchCoverImage(id, meta), ]); - const hasImage = consumet.map((i) => - i.episodes.some( - (e) => e.img !== null || !e.img.includes("https://s4.anilist.co/") - ) - ); + // const hasImage = consumet.map((i) => + // i.episodes?.sub?.some( + // (e) => e.img !== null || !e.img.includes("https://s4.anilist.co/") + // ) + // ); + + let subDub = "sub"; + if (dub) { + subDub = "dub"; + } - const rawData = [...consumet, ...(anify[0]?.data ?? [])]; + const rawData = [...consumet, ...anify]; - let data = rawData; + const filteredData = filterData(rawData, subDub); + + let data = filteredData; if (meta) { - data = await appendMetaToEpisodes(rawData, JSON.parse(meta)); - } else if (cover && cover?.length > 0 && !hasImage.includes(true)) - data = await appendImagesToEpisodes(rawData, cover); + data = await appendMetaToEpisodes(filteredData, JSON.parse(meta)); + } else if (cover && !cover.some((e) => e.img === null)) { + await redis.set(`meta:${id}`, JSON.stringify(cover)); + data = await appendMetaToEpisodes(filteredData, cover); + } if (redis && cacheTime !== null) { await redis.set( - id, - JSON.stringify(data.filter((i) => i.episodes.length > 0)), + `episode:${id}`, + JSON.stringify(rawData), "EX", cacheTime ); } if (dub) { - const filtered = data.filter((item) => - item.episodes.some((epi) => epi.hasDub === true) + const filtered = data.filter( + (item) => !item.episodes.some((epi) => epi.hasDub === false) ); - return res.status(200).json(filtered); + return res + .status(200) + .json(filtered.filter((i) => i.episodes.length > 0)); } console.log("fresh data"); diff --git a/pages/api/v2/etc/recent/[page].js b/pages/api/v2/etc/recent/[page].js index 6727787..b1bda0f 100644 --- a/pages/api/v2/etc/recent/[page].js +++ b/pages/api/v2/etc/recent/[page].js @@ -1,6 +1,10 @@ import { rateLimiterRedis, redis } from "@/lib/redis"; -const API_URL = process.env.API_URI; +let API_URL; +API_URL = process.env.API_URI; +if (API_URL.endsWith("/")) { + API_URL = API_URL.slice(0, -1); +} export default async function handler(req, res) { try { diff --git a/pages/api/v2/info/[id].js b/pages/api/v2/info/[id].js deleted file mode 100644 index 243756c..0000000 --- a/pages/api/v2/info/[id].js +++ /dev/null @@ -1,47 +0,0 @@ -import axios from "axios"; -import { rateLimiterRedis, redis } from "@/lib/redis"; - -const API_KEY = process.env.API_KEY; - -export async function fetchInfo(id) { - try { - const { data } = await axios.get( - `https://api.anify.tv/info/${id}?apikey=${API_KEY}` - ); - return data; - } catch (error) { - console.error("Error fetching data:", error); - return null; - } -} - -export default async function handler(req, res) { - const id = req.query.id; - let cached; - if (redis) { - try { - const ipAddress = req.socket.remoteAddress; - await rateLimiterRedis.consume(ipAddress); - } catch (error) { - return res.status(429).json({ - error: `Too Many Requests, retry after ${error.msBeforeNext / 1000}`, - }); - } - cached = await redis.get(id); - } - if (cached) { - // console.log("Using cached data"); - return res.status(200).json(JSON.parse(cached)); - } else { - const data = await fetchInfo(id); - if (data) { - // console.log("Setting cache"); - if (redis) { - await redis.set(id, JSON.stringify(data), "EX", 60 * 10); - } - return res.status(200).json(data); - } else { - return res.status(404).json({ message: "Schedule not found" }); - } - } -} diff --git a/pages/api/v2/info/index.js b/pages/api/v2/info/index.js new file mode 100644 index 0000000..95770bd --- /dev/null +++ b/pages/api/v2/info/index.js @@ -0,0 +1,60 @@ +import { redis } from "@/lib/redis"; +import axios from "axios"; + +const API_KEY = process.env.API_KEY; + +export async function fetchInfo(id) { + try { + // console.log(id); + const { data } = await axios + .get(`https://api.anify.tv/info/${id}?apikey=${API_KEY}`) + .catch((err) => { + return { + data: null, + }; + }); + + if (!data) { + return null; + } + + const { data: Chapters } = await axios.get( + `https://api.anify.tv/chapters/${data.id}?apikey=${API_KEY}` + ); + + if (!Chapters) { + return null; + } + + return { id: data.id, chapters: Chapters }; + } catch (error) { + console.error("Error fetching data:", error); + return null; + } +} + +export default async function handler(req, res) { + //const [romaji, english, native] = req.query.title; + const { id } = req.query; + try { + let cached; + // const data = await fetchInfo(id); + cached = await redis.get(`manga:${id}`); + + if (cached) { + return res.status(200).json(JSON.parse(cached)); + } + + const manga = await fetchInfo(id); + + if (!manga) { + return res.status(404).json({ error: "Manga not found" }); + } + + await redis.set(`manga:${id}`, JSON.stringify(manga), "ex", 60 * 60 * 24); + + res.status(200).json(manga); + } catch (error) { + res.status(500).json({ error: error.message }); + } +} diff --git a/pages/api/v2/pages/[...id].js b/pages/api/v2/pages/[...id].js new file mode 100644 index 0000000..a9fe0f9 --- /dev/null +++ b/pages/api/v2/pages/[...id].js @@ -0,0 +1,34 @@ +import axios from "axios"; + +async function fetchData(id, number, provider, readId) { + try { + const { data } = await axios.get( + `https://api.anify.tv/pages?id=${id}&chapterNumber=${number}&providerId=${provider}&readId=${encodeURIComponent( + readId + )}` + ); + + if (!data) { + return null; + } + + return data; + } catch (error) { + return null; + } +} + +export default async function handler(req, res) { + const [id, number, provider, readId] = req.query.id; + + try { + const data = await fetchData(id, number, provider, readId); + // if (!data) { + // return res.status(400).json({ error: "Invalid query" }); + // } + + return res.status(200).json(data); + } catch (error) { + return res.status(500).json({ error: error.message }); + } +} diff --git a/pages/api/v2/source/index.js b/pages/api/v2/source/index.js index f15e47d..9ec6082 100644 --- a/pages/api/v2/source/index.js +++ b/pages/api/v2/source/index.js @@ -1,7 +1,11 @@ import { rateLimiterRedis, redis } from "@/lib/redis"; import axios from "axios"; -const CONSUMET_URI = process.env.API_URI; +let CONSUMET_URI; +CONSUMET_URI = process.env.API_URI; +if (CONSUMET_URI.endsWith("/")) { + CONSUMET_URI = CONSUMET_URI.slice(0, -1); +} const API_KEY = process.env.API_KEY; async function consumetSource(id) { @@ -25,7 +29,7 @@ async function anifySource(providerId, watchId, episode, id, sub) { ); return data; } catch (error) { - return null; + return { error: error.message, status: error.response.status }; } } |