aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRitesh Ghosh <[email protected]>2023-12-17 19:45:22 +0530
committerGitHub <[email protected]>2023-12-17 19:45:22 +0530
commit948183d279e0a020a10011f99e9e5fbb7c8b3ef8 (patch)
tree29c3db39ad6778fdd8a676d0ae97ffe656df9bef /src
parent750386f04c5aec410ae54b1f2d0119271842c4da (diff)
parent8826dd276fe4a5ccab2b074d77191b81b265e528 (diff)
downloadaniwatch-api-948183d279e0a020a10011f99e9e5fbb7c8b3ef8.tar.xz
aniwatch-api-948183d279e0a020a10011f99e9e5fbb7c8b3ef8.zip
Merge pull request #13 from ghoshRitesh12/est-schedule
Add Estimated Schedule feature
Diffstat (limited to 'src')
-rw-r--r--src/controllers/estimatedSchedule.controller.ts36
-rw-r--r--src/controllers/index.ts2
-rw-r--r--src/models/controllers/estimatedSchedule.ts3
-rw-r--r--src/models/controllers/index.ts2
-rw-r--r--src/models/parsers/estimatedSchedule.ts10
-rw-r--r--src/models/parsers/index.ts2
-rw-r--r--src/parsers/estimatedSchedule.ts67
-rw-r--r--src/parsers/index.ts2
-rw-r--r--src/routes/index.ts4
9 files changed, 128 insertions, 0 deletions
diff --git a/src/controllers/estimatedSchedule.controller.ts b/src/controllers/estimatedSchedule.controller.ts
new file mode 100644
index 0000000..bead83e
--- /dev/null
+++ b/src/controllers/estimatedSchedule.controller.ts
@@ -0,0 +1,36 @@
+import createHttpError from "http-errors";
+import { type RequestHandler } from "express";
+import { scrapeEstimatedSchedule } from "../parsers/index.js";
+import { type EstimatedScheduleQueryParams } from "../models/controllers/index.js";
+
+// /anime/schedule?date=${date}
+const getEstimatedSchedule: RequestHandler<
+ unknown,
+ Awaited<ReturnType<typeof scrapeEstimatedSchedule>>,
+ unknown,
+ EstimatedScheduleQueryParams
+> = async (req, res, next) => {
+ try {
+ const dateQuery = req.query.date
+ ? decodeURIComponent(req.query.date as string)
+ : null;
+
+ if (dateQuery === null) {
+ throw createHttpError.BadRequest("Date payload required");
+ }
+ if (!/^\d{4}-\d{2}-\d{2}$/.test(dateQuery)) {
+ throw createHttpError.BadRequest(
+ "Invalid date payload format. Months and days must have 2 digits"
+ );
+ }
+
+ const data = await scrapeEstimatedSchedule(dateQuery);
+
+ res.status(200).json(data);
+ } catch (err: any) {
+ console.error(err);
+ next(err);
+ }
+};
+
+export default getEstimatedSchedule;
diff --git a/src/controllers/index.ts b/src/controllers/index.ts
index 21f9d10..6e90440 100644
--- a/src/controllers/index.ts
+++ b/src/controllers/index.ts
@@ -6,6 +6,7 @@ import getAnimeCategory from "./animeCategory.controller.js";
import getProducerAnimes from "./animeProducer.controller.js";
import getEpisodeServers from "./episodeServers.controller.js";
import getAnimeAboutInfo from "./animeAboutInfo.controller.js";
+import getEstimatedSchedule from "./estimatedSchedule.controller.js";
import getAnimeEpisodeSources from "./animeEpisodeSrcs.controller.js";
import getAnimeSearchSuggestion from "./animeSearchSuggestion.controller.js";
@@ -18,6 +19,7 @@ export {
getEpisodeServers,
getProducerAnimes,
getAnimeAboutInfo,
+ getEstimatedSchedule,
getAnimeEpisodeSources,
getAnimeSearchSuggestion,
};
diff --git a/src/models/controllers/estimatedSchedule.ts b/src/models/controllers/estimatedSchedule.ts
new file mode 100644
index 0000000..e732aaa
--- /dev/null
+++ b/src/models/controllers/estimatedSchedule.ts
@@ -0,0 +1,3 @@
+export type EstimatedScheduleQueryParams = {
+ date?: string;
+};
diff --git a/src/models/controllers/index.ts b/src/models/controllers/index.ts
index df9beff..fab25b6 100644
--- a/src/models/controllers/index.ts
+++ b/src/models/controllers/index.ts
@@ -15,6 +15,7 @@ import type { AnimeEpisodePathParams } from "./animeEpisodes.js";
import type { EpisodeServersQueryParams } from "./episodeServers.js";
import type { AnimeAboutInfoQueryParams } from "./animeAboutInfo.js";
import type { AnimeEpisodeSrcsQueryParams } from "./animeEpisodeSrcs.js";
+import type { EstimatedScheduleQueryParams } from "./estimatedSchedule.js";
import type { AnimeSearchSuggestQueryParams } from "./animeSearchSuggestion.js";
export type {
@@ -29,5 +30,6 @@ export type {
AnimeAboutInfoQueryParams,
EpisodeServersQueryParams,
AnimeEpisodeSrcsQueryParams,
+ EstimatedScheduleQueryParams,
AnimeSearchSuggestQueryParams,
};
diff --git a/src/models/parsers/estimatedSchedule.ts b/src/models/parsers/estimatedSchedule.ts
new file mode 100644
index 0000000..f62dd14
--- /dev/null
+++ b/src/models/parsers/estimatedSchedule.ts
@@ -0,0 +1,10 @@
+type EstimatedSchedule = {
+ id: string | null;
+ time: string | null;
+ name: string | null;
+ jname: string | null;
+};
+
+export type ScrapedEstimatedSchedule = {
+ scheduledAnimes: Array<EstimatedSchedule>;
+};
diff --git a/src/models/parsers/index.ts b/src/models/parsers/index.ts
index 2fb15af..057e2fc 100644
--- a/src/models/parsers/index.ts
+++ b/src/models/parsers/index.ts
@@ -6,6 +6,7 @@ import type { ScrapedProducerAnime } from "./animeProducer.js";
import type { ScrapedEpisodeServers } from "./episodeServers.js";
import type { ScrapedAnimeAboutInfo } from "./animeAboutInfo.js";
import type { ScrapedAnimeSearchResult } from "./animeSearch.js";
+import type { ScrapedEstimatedSchedule } from "./estimatedSchedule.js";
import type { ScrapedAnimeEpisodesSources } from "./animeEpisodeSrcs.js";
import type { ScrapedAnimeSearchSuggestion } from "./animeSearchSuggestion.js";
@@ -18,6 +19,7 @@ export type {
ScrapedEpisodeServers,
ScrapedAnimeAboutInfo,
ScrapedAnimeSearchResult,
+ ScrapedEstimatedSchedule,
ScrapedAnimeEpisodesSources,
ScrapedAnimeSearchSuggestion,
};
diff --git a/src/parsers/estimatedSchedule.ts b/src/parsers/estimatedSchedule.ts
new file mode 100644
index 0000000..b700054
--- /dev/null
+++ b/src/parsers/estimatedSchedule.ts
@@ -0,0 +1,67 @@
+import {
+ SRC_HOME_URL,
+ SRC_AJAX_URL,
+ USER_AGENT_HEADER,
+ ACCEPT_ENCODING_HEADER,
+} from "../utils/index.js";
+import axios, { AxiosError } from "axios";
+import createHttpError, { type HttpError } from "http-errors";
+import { load, type CheerioAPI, type SelectorType } from "cheerio";
+import { type ScrapedEstimatedSchedule } from "../models/parsers/index.js";
+
+// /anime/schedule?date=${date}
+async function scrapeEstimatedSchedule(
+ date: string
+): Promise<ScrapedEstimatedSchedule | HttpError> {
+ const res: ScrapedEstimatedSchedule = {
+ scheduledAnimes: [],
+ };
+
+ try {
+ const estScheduleURL =
+ `${SRC_AJAX_URL}/schedule/list?tzOffset=-330&date=${date}` as const;
+
+ const mainPage = await axios.get(estScheduleURL, {
+ headers: {
+ Accept: "*/*",
+ Referer: SRC_HOME_URL,
+ "User-Agent": USER_AGENT_HEADER,
+ "X-Requested-With": "XMLHttpRequest",
+ "Accept-Encoding": ACCEPT_ENCODING_HEADER,
+ },
+ });
+
+ const $: CheerioAPI = load(mainPage?.data?.html);
+
+ const selector: SelectorType = "li";
+
+ if ($(selector)?.text()?.trim()?.includes("No data to display")) {
+ return res;
+ }
+
+ $(selector).each((_, el) => {
+ res.scheduledAnimes.push({
+ id: $(el)?.find("a")?.attr("href")?.slice(1)?.trim() || null,
+ time: $(el)?.find("a .time")?.text()?.trim() || null,
+ name: $(el)?.find("a .film-name.dynamic-name")?.text()?.trim() || null,
+ jname:
+ $(el)
+ ?.find("a .film-name.dynamic-name")
+ ?.attr("data-jname")
+ ?.trim() || null,
+ });
+ });
+
+ return res;
+ } catch (err: any) {
+ if (err instanceof AxiosError) {
+ throw createHttpError(
+ err?.response?.status || 500,
+ err?.response?.statusText || "Something went wrong"
+ );
+ }
+ throw createHttpError.InternalServerError(err?.message);
+ }
+}
+
+export default scrapeEstimatedSchedule;
diff --git a/src/parsers/index.ts b/src/parsers/index.ts
index 49a78b9..395833a 100644
--- a/src/parsers/index.ts
+++ b/src/parsers/index.ts
@@ -6,6 +6,7 @@ import scrapeAnimeCategory from "./animeCategory.js";
import scrapeProducerAnimes from "./animeProducer.js";
import scrapeEpisodeServers from "./episodeServers.js";
import scrapeAnimeAboutInfo from "./animeAboutInfo.js";
+import scrapeEstimatedSchedule from "./estimatedSchedule.js";
import scrapeAnimeEpisodeSources from "./animeEpisodeSrcs.js";
import scrapeAnimeSearchSuggestion from "./animeSearchSuggestion.js";
@@ -18,6 +19,7 @@ export {
scrapeEpisodeServers,
scrapeProducerAnimes,
scrapeAnimeAboutInfo,
+ scrapeEstimatedSchedule,
scrapeAnimeEpisodeSources,
scrapeAnimeSearchSuggestion,
};
diff --git a/src/routes/index.ts b/src/routes/index.ts
index e3f6d8e..7046ae1 100644
--- a/src/routes/index.ts
+++ b/src/routes/index.ts
@@ -8,6 +8,7 @@ import {
getEpisodeServers,
getProducerAnimes,
getAnimeAboutInfo,
+ getEstimatedSchedule,
getAnimeEpisodeSources,
getAnimeSearchSuggestion,
} from "../controllers/index.js";
@@ -42,6 +43,9 @@ router.get("/servers", getEpisodeServers);
// /anime/episode-srcs?id=${episodeId}?server=${server}&category=${category (dub or sub)}
router.get("/episode-srcs", getAnimeEpisodeSources);
+// /anime/schedule?date=${date}
+router.get("/schedule", getEstimatedSchedule);
+
// /anime/producer/${name}?page=${page}
router.get("/producer/:name", getProducerAnimes);