diff --git a/build/server.js b/build/server.js index 87d105a..0eeafd4 100644 --- a/build/server.js +++ b/build/server.js @@ -8,10 +8,12 @@ const animeindoRoute_1 = __importDefault(require("./src/routes/animeindoRoute")) const cors_1 = __importDefault(require("cors")); const rateLimit_1 = __importDefault(require("./src/middleware/rateLimit")); require("dotenv/config"); +const morgan_1 = __importDefault(require("morgan")); const app = (0, express_1.default)(); const port = process.env.PORT || 8000; app.use(express_1.default.json()); app.use(rateLimit_1.default); +app.use((0, morgan_1.default)("combined")); app.use((0, cors_1.default)({ origin: process.env.CORS_ORIGIN, credentials: true, diff --git a/build/src/controllers/animeindoController.js b/build/src/controllers/animeindoController.js index 63a3a81..64c7aac 100644 --- a/build/src/controllers/animeindoController.js +++ b/build/src/controllers/animeindoController.js @@ -26,7 +26,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); -exports.getAnimeByEpisode = exports.getAnimeBySchedule = exports.getAnimeByGenre = exports.getAnimePropertiesGenre = exports.getAnimeBySeasonList = exports.getAnimeByDetails = exports.getAnimeSeasonList = exports.getAnimeMovie = exports.getAnimeLatest = exports.getAnimeOnGoing = void 0; +exports.getAnimeByEpisode = exports.getAnimeBySchedule = exports.getAnimeByGenre = exports.getAnimePropertiesGenre = exports.getAnimeByDetails = exports.getAnimeBySeasonList = exports.getAnimeSeasonList = exports.getAnimeMovie = exports.getAnimeLatest = exports.getAnimeOnGoing = void 0; const cheerio = __importStar(require("cheerio")); const request_1 = __importDefault(require("request")); const baseURL_1 = require("../lib/baseURL"); @@ -35,7 +35,7 @@ const getAnimeOnGoing = (req, res) => { return new Promise((resolve, reject) => { try { const options = { - url: `${baseURL_1.baseURL}/quick/ongoing?order_by=${order_by || "ongoing"}&page=${page || 1}`, + url: `${baseURL_1.baseURL}/quick/ongoing?order_by=${order_by || "updated"}&page=${page || 1}`, }; let has_next_page = false; let has_prev_page = false; @@ -301,7 +301,6 @@ const getAnimeMovie = (req, res) => { }; exports.getAnimeMovie = getAnimeMovie; const getAnimeSeasonList = (req, res) => { - const { page } = req.query; return new Promise((resolve, reject) => { try { const options = { @@ -319,7 +318,7 @@ const getAnimeSeasonList = (req, res) => { $("#animeList > div > div > ul > li").each((index, el) => { var _a, _b, _c, _d, _e, _f, _g; const season_title = (_c = (_b = (_a = $(el) - .find("a") + .find("a > span") .text()) === null || _a === void 0 ? void 0 : _a.replace(/\n/g, "")) === null || _b === void 0 ? void 0 : _b.trim()) === null || _c === void 0 ? void 0 : _c.replace(/"/g, ""); const season_slug = (_g = (_f = (_e = (_d = $(el) .find("a") @@ -337,6 +336,7 @@ const getAnimeSeasonList = (req, res) => { }); } catch (error) { + console.log(error); res.status(500).json({ status: "error", message: error.message, @@ -346,6 +346,73 @@ const getAnimeSeasonList = (req, res) => { }); }; exports.getAnimeSeasonList = getAnimeSeasonList; +const getAnimeBySeasonList = (req, res) => { + const { order_by, page } = req.query; + const { season_id } = req.params; + return new Promise((resolve, reject) => { + try { + const options = { + url: `${baseURL_1.baseURL}/properties/season/${season_id}?order_by=${order_by || "most_viewed"}&page=${page || 1}`, + }; + const animeList = []; + (0, request_1.default)(options, (error, response, body) => { + if (error || response.statusCode !== 200) { + return res.status(500).json({ + status: "error", + message: "Failed to retrieve anime list", + }); + } + const $ = cheerio.load(body); + $("#animeList > div > div").each((index, el) => { + var _a, _b, _c, _d, _e, _f; + const typeList = $(el) + .find("div > ul > a") + .map((i, index) => $(index).text()) + .get(); + const slug = (_a = $(el) + .find("div > a") + .attr("href")) === null || _a === void 0 ? void 0 : _a.replace(baseURL_1.baseURL, ""); + const title = (_d = (_c = (_b = $(el) + .find("div > h5") + .text()) === null || _b === void 0 ? void 0 : _b.replace(/\n/g, "")) === null || _c === void 0 ? void 0 : _c.trim()) === null || _d === void 0 ? void 0 : _d.replace(/"/g, ""); + const rating = (_f = (_e = $(el) + .find("a > div > div.ep > span") + .text()) === null || _e === void 0 ? void 0 : _e.replace(/\n/g, "")) === null || _f === void 0 ? void 0 : _f.trim(); + const image = $(el).find("a > div").attr("data-setbg"); + animeList.push({ + type: typeList, + slug, + title, + rating, + image, + }); + }); + const filteredAnimeList = animeList.filter((anime) => { + return anime.type.length > 0 || anime.title || anime.episode; + }); + if (filteredAnimeList.length === 0) { + return res.status(404).json({ + status: "error", + message: "No anime found", + }); + } + res.status(200).json({ + status: "success", + data: filteredAnimeList, + }); + resolve(); + }); + } + catch (error) { + res.status(500).json({ + status: "error", + message: error.message, + }); + reject(error); + } + }); +}; +exports.getAnimeBySeasonList = getAnimeBySeasonList; const getAnimeByDetails = (req, res) => { const { page } = req.query; const { anime_code, anime_id } = req.params; @@ -490,73 +557,6 @@ const getAnimeByDetails = (req, res) => { }); }; exports.getAnimeByDetails = getAnimeByDetails; -const getAnimeBySeasonList = (req, res) => { - const { order_by, page } = req.query; - const { season_id } = req.params; - return new Promise((resolve, reject) => { - try { - const options = { - url: `${baseURL_1.baseURL}/properties/season/${season_id}?order_by=${order_by || "most_viewed"}&page=${page || 1}`, - }; - const animeList = []; - (0, request_1.default)(options, (error, response, body) => { - if (error || response.statusCode !== 200) { - return res.status(500).json({ - status: "error", - message: "Failed to retrieve anime list", - }); - } - const $ = cheerio.load(body); - $("#animeList > div > div").each((index, el) => { - var _a, _b, _c, _d, _e, _f; - const typeList = $(el) - .find("div > ul > a") - .map((i, index) => $(index).text()) - .get(); - const slug = (_a = $(el) - .find("div > a") - .attr("href")) === null || _a === void 0 ? void 0 : _a.replace(baseURL_1.baseURL, ""); - const title = (_d = (_c = (_b = $(el) - .find("div > h5") - .text()) === null || _b === void 0 ? void 0 : _b.replace(/\n/g, "")) === null || _c === void 0 ? void 0 : _c.trim()) === null || _d === void 0 ? void 0 : _d.replace(/"/g, ""); - const rating = (_f = (_e = $(el) - .find("a > div > div.ep > span") - .text()) === null || _e === void 0 ? void 0 : _e.replace(/\n/g, "")) === null || _f === void 0 ? void 0 : _f.trim(); - const image = $(el).find("a > div").attr("data-setbg"); - animeList.push({ - type: typeList, - slug, - title, - rating, - image, - }); - }); - const filteredAnimeList = animeList.filter((anime) => { - return anime.type.length > 0 || anime.title || anime.episode; - }); - if (filteredAnimeList.length === 0) { - return res.status(404).json({ - status: "error", - message: "No anime found", - }); - } - res.status(200).json({ - status: "success", - data: filteredAnimeList, - }); - resolve(); - }); - } - catch (error) { - res.status(500).json({ - status: "error", - message: error.message, - }); - reject(error); - } - }); -}; -exports.getAnimeBySeasonList = getAnimeBySeasonList; const getAnimePropertiesGenre = (req, res) => { const { page } = req.query; return new Promise((resolve, reject) => { @@ -750,7 +750,7 @@ const getAnimeByEpisode = (req, res) => { const { anime_code, anime_id, episode_id } = req.params; const { page } = req.query; const options = { - url: `${baseURL_1.baseURL}/anime/${anime_code}/${anime_id}/episode/${episode_id}?YufB6E2rKx3pM0F=iV2Ymxtsfa&1cerLmDzYXioTFa=kuramadrive&page=${page || 1}`, + url: `${baseURL_1.baseURL}/anime/${anime_code}/${anime_id}/episode/${episode_id}?QXCKFC2hpmVFvvv=8vIFROsi7w&PsAdpiUFrAc3n85=kuramadrive&page=${page || 1}`, }; let has_next_page = false; let has_next_link = null; @@ -821,7 +821,6 @@ const getAnimeByEpisode = (req, res) => { status: "error", message: error.message, }); - reject(error); } }); }; diff --git a/build/src/routes/animeindoRoute.js b/build/src/routes/animeindoRoute.js index 688c1dd..45da250 100644 --- a/build/src/routes/animeindoRoute.js +++ b/build/src/routes/animeindoRoute.js @@ -7,9 +7,9 @@ animeIndo.get("/ongoing", animeindoController_1.getAnimeOnGoing); animeIndo.get("/completed", animeindoController_1.getAnimeLatest); animeIndo.get("/movie", animeindoController_1.getAnimeMovie); animeIndo.get("/:anime_code/:anime_id", animeindoController_1.getAnimeByDetails); -animeIndo.get("/properties/season", animeindoController_1.getAnimeSeasonList); +animeIndo.get("/properties/season/list", animeindoController_1.getAnimeSeasonList); animeIndo.get("/properties/season/:season_id", animeindoController_1.getAnimeBySeasonList); -animeIndo.get("/properties/genre", animeindoController_1.getAnimePropertiesGenre); +animeIndo.get("/properties/genre/list", animeindoController_1.getAnimePropertiesGenre); animeIndo.get("/properties/genre/:genre_id", animeindoController_1.getAnimeByGenre); animeIndo.get("/schedule", animeindoController_1.getAnimeBySchedule); animeIndo.get("/:anime_code/:anime_id/episode/:episode_id", animeindoController_1.getAnimeByEpisode); diff --git a/package-lock.json b/package-lock.json index 62d7a52..6aac21b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,11 +14,13 @@ "dotenv": "^16.4.5", "express": "^4.19.2", "express-rate-limit": "^7.3.1", + "morgan": "^1.10.0", "request": "^2.88.2" }, "devDependencies": { "@types/cors": "^2.8.17", "@types/express": "^4.17.21", + "@types/morgan": "^1.9.9", "@types/request": "^2.48.12", "nodemon": "^3.1.4", "ts-node": "^10.9.2", @@ -157,6 +159,15 @@ "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", "dev": true }, + "node_modules/@types/morgan": { + "version": "1.9.9", + "resolved": "https://registry.npmjs.org/@types/morgan/-/morgan-1.9.9.tgz", + "integrity": "sha512-iRYSDKVaC6FkGSpEVVIvrRGw0DfJMiQzIn3qr2G5B3C//AWkulhXgaBd7tS9/J79GWSYMTHGs7PfI5b3Y8m+RQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/node": { "version": "20.14.10", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.10.tgz", @@ -358,6 +369,22 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, + "node_modules/basic-auth": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", + "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", + "dependencies": { + "safe-buffer": "5.1.2" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/basic-auth/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, "node_modules/bcrypt-pbkdf": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", @@ -1410,6 +1437,32 @@ "node": ">=10" } }, + "node_modules/morgan": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.10.0.tgz", + "integrity": "sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ==", + "dependencies": { + "basic-auth": "~2.0.1", + "debug": "2.6.9", + "depd": "~2.0.0", + "on-finished": "~2.3.0", + "on-headers": "~1.0.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/morgan/node_modules/on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", @@ -1532,6 +1585,14 @@ "node": ">= 0.8" } }, + "node_modules/on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", diff --git a/package.json b/package.json index b63ebf2..d481362 100644 --- a/package.json +++ b/package.json @@ -18,11 +18,13 @@ "dotenv": "^16.4.5", "express": "^4.19.2", "express-rate-limit": "^7.3.1", + "morgan": "^1.10.0", "request": "^2.88.2" }, "devDependencies": { "@types/cors": "^2.8.17", "@types/express": "^4.17.21", + "@types/morgan": "^1.9.9", "@types/request": "^2.48.12", "nodemon": "^3.1.4", "ts-node": "^10.9.2", diff --git a/server.ts b/server.ts index 475b2b7..eb8d289 100644 --- a/server.ts +++ b/server.ts @@ -3,12 +3,14 @@ import animeIndo from "./src/routes/animeindoRoute"; import cors from "cors"; import limiter from "./src/middleware/rateLimit"; import "dotenv/config"; +import morgan from "morgan"; const app: Application = express(); const port = process.env.PORT || 8000; app.use(express.json()); app.use(limiter); +app.use(morgan("combined")); app.use( cors({ origin: process.env.CORS_ORIGIN, diff --git a/src/controllers/animeindoController.ts b/src/controllers/animeindoController.ts index 6e98f6f..8910369 100644 --- a/src/controllers/animeindoController.ts +++ b/src/controllers/animeindoController.ts @@ -9,7 +9,7 @@ export const getAnimeOnGoing = (req: Request, res: Response): Promise => { return new Promise((resolve, reject) => { try { const options = { - url: `${baseURL}/quick/ongoing?order_by=${order_by || "ongoing"}&page=${ + url: `${baseURL}/quick/ongoing?order_by=${order_by || "updated"}&page=${ page || 1 }`, }; @@ -372,7 +372,6 @@ export const getAnimeSeasonList = ( req: Request, res: Response ): Promise => { - const { page } = req.query; return new Promise((resolve, reject) => { try { const options = { @@ -395,7 +394,7 @@ export const getAnimeSeasonList = ( $("#animeList > div > div > ul > li").each((index, el) => { const season_title = $(el) - .find("a") + .find("a > span") .text() ?.replace(/\n/g, "") ?.trim() @@ -424,6 +423,99 @@ export const getAnimeSeasonList = ( } ); } catch (error: any) { + console.log(error); + res.status(500).json({ + status: "error", + message: error.message, + }); + reject(error); + } + }); +}; + +export const getAnimeBySeasonList = ( + req: Request, + res: Response +): Promise => { + const { order_by, page } = req.query; + const { season_id } = req.params; + return new Promise((resolve, reject) => { + try { + const options = { + url: `${baseURL}/properties/season/${season_id}?order_by=${ + order_by || "most_viewed" + }&page=${page || 1}`, + }; + + const animeList: Array = []; + + request( + options, + (error: Error | null, response: IncomingMessage, body: string) => { + if (error || response.statusCode !== 200) { + return res.status(500).json({ + status: "error", + message: "Failed to retrieve anime list", + }); + } + + const $ = cheerio.load(body); + + $("#animeList > div > div").each((index, el) => { + const typeList = $(el) + .find("div > ul > a") + .map((i, index) => $(index).text()) + .get(); + + const slug = $(el) + .find("div > a") + .attr("href") + ?.replace(baseURL, ""); + + const title = $(el) + .find("div > h5") + .text() + ?.replace(/\n/g, "") + ?.trim() + ?.replace(/"/g, ""); + + const rating = $(el) + .find("a > div > div.ep > span") + .text() + ?.replace(/\n/g, "") + ?.trim(); + + const image = $(el).find("a > div").attr("data-setbg"); + + animeList.push({ + type: typeList, + slug, + title, + rating, + image, + }); + }); + + const filteredAnimeList = animeList.filter((anime) => { + return anime.type.length > 0 || anime.title || anime.episode; + }); + + if (filteredAnimeList.length === 0) { + return res.status(404).json({ + status: "error", + message: "No anime found", + }); + } + + res.status(200).json({ + status: "success", + data: filteredAnimeList, + }); + + resolve(); + } + ); + } catch (error: any) { res.status(500).json({ status: "error", message: error.message, @@ -650,98 +742,6 @@ export const getAnimeByDetails = ( }); }; -export const getAnimeBySeasonList = ( - req: Request, - res: Response -): Promise => { - const { order_by, page } = req.query; - const { season_id } = req.params; - return new Promise((resolve, reject) => { - try { - const options = { - url: `${baseURL}/properties/season/${season_id}?order_by=${ - order_by || "most_viewed" - }&page=${page || 1}`, - }; - - const animeList: Array = []; - - request( - options, - (error: Error | null, response: IncomingMessage, body: string) => { - if (error || response.statusCode !== 200) { - return res.status(500).json({ - status: "error", - message: "Failed to retrieve anime list", - }); - } - - const $ = cheerio.load(body); - - $("#animeList > div > div").each((index, el) => { - const typeList = $(el) - .find("div > ul > a") - .map((i, index) => $(index).text()) - .get(); - - const slug = $(el) - .find("div > a") - .attr("href") - ?.replace(baseURL, ""); - - const title = $(el) - .find("div > h5") - .text() - ?.replace(/\n/g, "") - ?.trim() - ?.replace(/"/g, ""); - - const rating = $(el) - .find("a > div > div.ep > span") - .text() - ?.replace(/\n/g, "") - ?.trim(); - - const image = $(el).find("a > div").attr("data-setbg"); - - animeList.push({ - type: typeList, - slug, - title, - rating, - image, - }); - }); - - const filteredAnimeList = animeList.filter((anime) => { - return anime.type.length > 0 || anime.title || anime.episode; - }); - - if (filteredAnimeList.length === 0) { - return res.status(404).json({ - status: "error", - message: "No anime found", - }); - } - - res.status(200).json({ - status: "success", - data: filteredAnimeList, - }); - - resolve(); - } - ); - } catch (error: any) { - res.status(500).json({ - status: "error", - message: error.message, - }); - reject(error); - } - }); -}; - export const getAnimePropertiesGenre = ( req: Request, res: Response @@ -1008,7 +1008,7 @@ export const getAnimeByEpisode = ( const { anime_code, anime_id, episode_id } = req.params; const { page } = req.query; const options = { - url: `${baseURL}/anime/${anime_code}/${anime_id}/episode/${episode_id}?YufB6E2rKx3pM0F=iV2Ymxtsfa&1cerLmDzYXioTFa=kuramadrive&page=${ + url: `${baseURL}/anime/${anime_code}/${anime_id}/episode/${episode_id}?QXCKFC2hpmVFvvv=8vIFROsi7w&PsAdpiUFrAc3n85=kuramadrive&page=${ page || 1 }`, }; @@ -1091,7 +1091,6 @@ export const getAnimeByEpisode = ( status: "error", message: error.message, }); - reject(error); } }); }; diff --git a/src/routes/animeindoRoute.ts b/src/routes/animeindoRoute.ts index d85fe2f..ff38aab 100644 --- a/src/routes/animeindoRoute.ts +++ b/src/routes/animeindoRoute.ts @@ -5,11 +5,11 @@ import { getAnimeBySeasonList, getAnimeOnGoing, getAnimePropertiesGenre, - getAnimeSeasonList, getAnimeByDetails, getAnimeByEpisode, getAnimeLatest, getAnimeMovie, + getAnimeSeasonList, } from "../controllers/animeindoController"; const animeIndo = Router(); @@ -20,10 +20,10 @@ animeIndo.get("/movie", getAnimeMovie); animeIndo.get("/:anime_code/:anime_id", getAnimeByDetails); -animeIndo.get("/properties/season", getAnimeSeasonList); +animeIndo.get("/properties/season/list", getAnimeSeasonList); animeIndo.get("/properties/season/:season_id", getAnimeBySeasonList); -animeIndo.get("/properties/genre", getAnimePropertiesGenre); +animeIndo.get("/properties/genre/list", getAnimePropertiesGenre); animeIndo.get("/properties/genre/:genre_id", getAnimeByGenre); animeIndo.get("/schedule", getAnimeBySchedule);