From f5cd3415d8134da1ab1e3b3f8f9be6b5212aa353 Mon Sep 17 00:00:00 2001 From: Ritesh Ghosh Date: Tue, 15 Apr 2025 00:11:22 +0530 Subject: [PATCH] feat(getNextEpisodeSchedule): add `/anime/:animeId/next-episode-schedule` endpoint --- src/routes/hianime.ts | 277 ++++++++++++++++++++++-------------------- 1 file changed, 148 insertions(+), 129 deletions(-) diff --git a/src/routes/hianime.ts b/src/routes/hianime.ts index 7aab3ff..38242c0 100644 --- a/src/routes/hianime.ts +++ b/src/routes/hianime.ts @@ -11,211 +11,230 @@ hianimeRouter.get("/", (c) => c.redirect("/", 301)); // /api/v2/hianime/home hianimeRouter.get("/home", async (c) => { - const cacheConfig = c.get("CACHE_CONFIG"); + const cacheConfig = c.get("CACHE_CONFIG"); - const data = await cache.getOrSet( - hianime.getHomePage, - cacheConfig.key, - cacheConfig.duration - ); + const data = await cache.getOrSet( + hianime.getHomePage, + cacheConfig.key, + cacheConfig.duration + ); - return c.json({ success: true, data }, { status: 200 }); + return c.json({ success: true, data }, { status: 200 }); }); // /api/v2/hianime/azlist/{sortOption}?page={page} hianimeRouter.get("/azlist/:sortOption", async (c) => { - const cacheConfig = c.get("CACHE_CONFIG"); + const cacheConfig = c.get("CACHE_CONFIG"); - const sortOption = decodeURIComponent( - c.req.param("sortOption").trim().toLowerCase() - ) as HiAnime.AZListSortOptions; - const page: number = - Number(decodeURIComponent(c.req.query("page") || "")) || 1; + const sortOption = decodeURIComponent( + c.req.param("sortOption").trim().toLowerCase() + ) as HiAnime.AZListSortOptions; + const page: number = + Number(decodeURIComponent(c.req.query("page") || "")) || 1; - const data = await cache.getOrSet( - async () => hianime.getAZList(sortOption, page), - cacheConfig.key, - cacheConfig.duration - ); + const data = await cache.getOrSet( + async () => hianime.getAZList(sortOption, page), + cacheConfig.key, + cacheConfig.duration + ); - return c.json({ success: true, data }, { status: 200 }); + return c.json({ success: true, data }, { status: 200 }); }); // /api/v2/hianime/qtip/{animeId} hianimeRouter.get("/qtip/:animeId", async (c) => { - const cacheConfig = c.get("CACHE_CONFIG"); - const animeId = decodeURIComponent(c.req.param("animeId").trim()); + const cacheConfig = c.get("CACHE_CONFIG"); + const animeId = decodeURIComponent(c.req.param("animeId").trim()); - const data = await cache.getOrSet( - async () => hianime.getQtipInfo(animeId), - cacheConfig.key, - cacheConfig.duration - ); + const data = await cache.getOrSet( + async () => hianime.getQtipInfo(animeId), + cacheConfig.key, + cacheConfig.duration + ); - return c.json({ success: true, data }, { status: 200 }); + return c.json({ success: true, data }, { status: 200 }); }); // /api/v2/hianime/category/{name}?page={page} hianimeRouter.get("/category/:name", async (c) => { - const cacheConfig = c.get("CACHE_CONFIG"); - const categoryName = decodeURIComponent( - c.req.param("name").trim() - ) as HiAnime.AnimeCategories; - const page: number = - Number(decodeURIComponent(c.req.query("page") || "")) || 1; + const cacheConfig = c.get("CACHE_CONFIG"); + const categoryName = decodeURIComponent( + c.req.param("name").trim() + ) as HiAnime.AnimeCategories; + const page: number = + Number(decodeURIComponent(c.req.query("page") || "")) || 1; - const data = await cache.getOrSet( - async () => hianime.getCategoryAnime(categoryName, page), - cacheConfig.key, - cacheConfig.duration - ); + const data = await cache.getOrSet( + async () => hianime.getCategoryAnime(categoryName, page), + cacheConfig.key, + cacheConfig.duration + ); - return c.json({ success: true, data }, { status: 200 }); + return c.json({ success: true, data }, { status: 200 }); }); // /api/v2/hianime/genre/{name}?page={page} hianimeRouter.get("/genre/:name", async (c) => { - const cacheConfig = c.get("CACHE_CONFIG"); - const genreName = decodeURIComponent(c.req.param("name").trim()); - const page: number = - Number(decodeURIComponent(c.req.query("page") || "")) || 1; + const cacheConfig = c.get("CACHE_CONFIG"); + const genreName = decodeURIComponent(c.req.param("name").trim()); + const page: number = + Number(decodeURIComponent(c.req.query("page") || "")) || 1; - const data = await cache.getOrSet( - async () => hianime.getGenreAnime(genreName, page), - cacheConfig.key, - cacheConfig.duration - ); + const data = await cache.getOrSet( + async () => hianime.getGenreAnime(genreName, page), + cacheConfig.key, + cacheConfig.duration + ); - return c.json({ success: true, data }, { status: 200 }); + return c.json({ success: true, data }, { status: 200 }); }); // /api/v2/hianime/producer/{name}?page={page} hianimeRouter.get("/producer/:name", async (c) => { - const cacheConfig = c.get("CACHE_CONFIG"); - const producerName = decodeURIComponent(c.req.param("name").trim()); - const page: number = - Number(decodeURIComponent(c.req.query("page") || "")) || 1; + const cacheConfig = c.get("CACHE_CONFIG"); + const producerName = decodeURIComponent(c.req.param("name").trim()); + const page: number = + Number(decodeURIComponent(c.req.query("page") || "")) || 1; - const data = await cache.getOrSet( - async () => hianime.getProducerAnimes(producerName, page), - cacheConfig.key, - cacheConfig.duration - ); + const data = await cache.getOrSet( + async () => hianime.getProducerAnimes(producerName, page), + cacheConfig.key, + cacheConfig.duration + ); - return c.json({ success: true, data }, { status: 200 }); + return c.json({ success: true, data }, { status: 200 }); }); -// /api/v2/hianime/schedule?date={date} +// /api/v2/hianime/schedule?date={date}&tzOffset={tzOffset} hianimeRouter.get("/schedule", async (c) => { - const cacheConfig = c.get("CACHE_CONFIG"); - const date = decodeURIComponent(c.req.query("date") || ""); + const cacheConfig = c.get("CACHE_CONFIG"); - const data = await cache.getOrSet( - async () => hianime.getEstimatedSchedule(date), - cacheConfig.key, - cacheConfig.duration - ); + const date = decodeURIComponent(c.req.query("date") || ""); + let tzOffset = Number( + decodeURIComponent(c.req.query("tzOffset") || "-330") + ); + tzOffset = isNaN(tzOffset) ? -330 : tzOffset; - return c.json({ success: true, data }, { status: 200 }); + const data = await cache.getOrSet( + async () => hianime.getEstimatedSchedule(date, tzOffset), + `${cacheConfig.key}_${tzOffset}`, + cacheConfig.duration + ); + + return c.json({ success: true, data }, { status: 200 }); }); // /api/v2/hianime/search?q={query}&page={page}&filters={...filters} hianimeRouter.get("/search", async (c) => { - const cacheConfig = c.get("CACHE_CONFIG"); - let { q: query, page, ...filters } = c.req.query(); + const cacheConfig = c.get("CACHE_CONFIG"); + let { q: query, page, ...filters } = c.req.query(); - query = decodeURIComponent(query || ""); - const pageNo = Number(decodeURIComponent(page || "")) || 1; + query = decodeURIComponent(query || ""); + const pageNo = Number(decodeURIComponent(page || "")) || 1; - const data = await cache.getOrSet( - async () => hianime.search(query, pageNo, filters), - cacheConfig.key, - cacheConfig.duration - ); + const data = await cache.getOrSet( + async () => hianime.search(query, pageNo, filters), + cacheConfig.key, + cacheConfig.duration + ); - return c.json({ success: true, data }, { status: 200 }); + return c.json({ success: true, data }, { status: 200 }); }); // /api/v2/hianime/search/suggestion?q={query} hianimeRouter.get("/search/suggestion", async (c) => { - const cacheConfig = c.get("CACHE_CONFIG"); - const query = decodeURIComponent(c.req.query("q") || ""); + const cacheConfig = c.get("CACHE_CONFIG"); + const query = decodeURIComponent(c.req.query("q") || ""); - const data = await cache.getOrSet( - async () => hianime.searchSuggestions(query), - cacheConfig.key, - cacheConfig.duration - ); + const data = await cache.getOrSet( + async () => hianime.searchSuggestions(query), + cacheConfig.key, + cacheConfig.duration + ); - return c.json({ success: true, data }, { status: 200 }); + return c.json({ success: true, data }, { status: 200 }); }); // /api/v2/hianime/anime/{animeId} hianimeRouter.get("/anime/:animeId", async (c) => { - const cacheConfig = c.get("CACHE_CONFIG"); - const animeId = decodeURIComponent(c.req.param("animeId").trim()); + const cacheConfig = c.get("CACHE_CONFIG"); + const animeId = decodeURIComponent(c.req.param("animeId").trim()); - const data = await cache.getOrSet( - async () => hianime.getInfo(animeId), - cacheConfig.key, - cacheConfig.duration - ); + const data = await cache.getOrSet( + async () => hianime.getInfo(animeId), + cacheConfig.key, + cacheConfig.duration + ); - return c.json({ success: true, data }, { status: 200 }); + return c.json({ success: true, data }, { status: 200 }); }); // /api/v2/hianime/episode/servers?animeEpisodeId={id} hianimeRouter.get("/episode/servers", async (c) => { - const cacheConfig = c.get("CACHE_CONFIG"); - const animeEpisodeId = decodeURIComponent( - c.req.query("animeEpisodeId") || "" - ); + const cacheConfig = c.get("CACHE_CONFIG"); + const animeEpisodeId = decodeURIComponent( + c.req.query("animeEpisodeId") || "" + ); - const data = await cache.getOrSet( - async () => hianime.getEpisodeServers(animeEpisodeId), - cacheConfig.key, - cacheConfig.duration - ); + const data = await cache.getOrSet( + async () => hianime.getEpisodeServers(animeEpisodeId), + cacheConfig.key, + cacheConfig.duration + ); - return c.json({ success: true, data }, { status: 200 }); + return c.json({ success: true, data }, { status: 200 }); }); // episodeId=steinsgate-3?ep=230 // /api/v2/hianime/episode/sources?animeEpisodeId={episodeId}?server={server}&category={category (dub or sub)} hianimeRouter.get("/episode/sources", async (c) => { - const cacheConfig = c.get("CACHE_CONFIG"); - const animeEpisodeId = decodeURIComponent( - c.req.query("animeEpisodeId") || "" - ); - const server = decodeURIComponent( - c.req.query("server") || HiAnime.Servers.VidStreaming - ) as HiAnime.AnimeServers; - const category = decodeURIComponent(c.req.query("category") || "sub") as - | "sub" - | "dub" - | "raw"; + const cacheConfig = c.get("CACHE_CONFIG"); + const animeEpisodeId = decodeURIComponent( + c.req.query("animeEpisodeId") || "" + ); + const server = decodeURIComponent( + c.req.query("server") || HiAnime.Servers.VidStreaming + ) as HiAnime.AnimeServers; + const category = decodeURIComponent(c.req.query("category") || "sub") as + | "sub" + | "dub" + | "raw"; - const data = await cache.getOrSet( - async () => hianime.getEpisodeSources(animeEpisodeId, server, category), - cacheConfig.key, - cacheConfig.duration - ); + const data = await cache.getOrSet( + async () => hianime.getEpisodeSources(animeEpisodeId, server, category), + cacheConfig.key, + cacheConfig.duration + ); - return c.json({ success: true, data }, { status: 200 }); + return c.json({ success: true, data }, { status: 200 }); }); // /api/v2/hianime/anime/{anime-id}/episodes hianimeRouter.get("/anime/:animeId/episodes", async (c) => { - const cacheConfig = c.get("CACHE_CONFIG"); - const animeId = decodeURIComponent(c.req.param("animeId").trim()); + const cacheConfig = c.get("CACHE_CONFIG"); + const animeId = decodeURIComponent(c.req.param("animeId").trim()); - const data = await cache.getOrSet( - async () => hianime.getEpisodes(animeId), - cacheConfig.key, - cacheConfig.duration - ); + const data = await cache.getOrSet( + async () => hianime.getEpisodes(animeId), + cacheConfig.key, + cacheConfig.duration + ); - return c.json({ success: true, data }, { status: 200 }); + return c.json({ success: true, data }, { status: 200 }); +}); + +// /api/v2/hianime/anime/{anime-id}/next-episode-schedule +hianimeRouter.get("/anime/:animeId/next-episode-schedule", async (c) => { + const cacheConfig = c.get("CACHE_CONFIG"); + const animeId = decodeURIComponent(c.req.param("animeId").trim()); + + const data = await cache.getOrSet( + async () => hianime.getNextEpisodeSchedule(animeId), + cacheConfig.key, + cacheConfig.duration + ); + + return c.json({ success: true, data }, { status: 200 }); }); export { hianimeRouter };