UNPKG

hianime

Version:
208 lines 7.66 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const axios_1 = __importDefault(require("axios")); const cheerio = __importStar(require("cheerio")); class Hianime { BASE_URL = "https://hianime.to"; async getAnimeList(category, page = 1) { const { data } = await axios_1.default.get(`${this.BASE_URL}/${category}`, { params: { page: page, }, }); const $ = cheerio.load(data); const animeList = $(".tab-content div.film_list-wrap > div.flw-item") .map((_, element) => { const anime = { id: $(element).find("a[data-id]").attr("href"), image: $(element).find("div.film-poster > img").attr("data-src"), title: $(element) .find("div.film-detail > .film-name > a") .attr("title"), type: $(element) .find("div.fd-infor > span.fdi-item") .first() .text() .toUpperCase(), language: { sub: $(element).find(".tick.ltr > .tick-sub").text() || null, dub: $(element).find(".tick.ltr > .tick-dub").text() || null, }, dataId: $(element).find("a[data-id]").attr("data-id"), }; return anime; }) .get(); const totalPage = parseInt($('a[title="Last"]').attr("href")?.split("=")[1] ?? page.toString()); return { page, totalPage, hasNextPage: page < totalPage, results: animeList, }; } async getSubbedAnime(page = 1) { return this.getAnimeList("subbed-anime", page); } async getDubbedAnime(page = 1) { return this.getAnimeList("dubbed-anime", page); } async getMostPopular(page = 1) { return this.getAnimeList("most-popular", page); } async getMovies(page = 1) { return this.getAnimeList("movie", page); } async getTVShows(page = 1) { return this.getAnimeList("tv", page); } async getSpecialList(page = 1) { return this.getAnimeList("special", page); } async getONAList(page = 1) { return this.getAnimeList("ona", page); } async getOVAList(page = 1) { return this.getAnimeList("ova", page); } async getTopAiring(page = 1) { return this.getAnimeList("top-airing", page); } async getEpisodes(dataId) { const { data } = await axios_1.default.get(`${this.BASE_URL}/ajax/v2/episode/list/${dataId}`); const $ = cheerio.load(data.html); const episodes = $("div.ss-list > a.ep-item") .map((_, element) => { const episode = { id: $(element).attr("data-id"), number: $(element).attr("data-number"), title: $(element).attr("title"), href: $(element).attr("href"), }; return episode; }) .get(); return episodes; } async getEpisodeServers(episodeId) { const { data } = await axios_1.default.get(`${this.BASE_URL}/ajax/v2/episode/servers`, { params: { episodeId, }, }); const $ = cheerio.load(data.html); const subServers = $("div.servers-sub .server-item") .map((_, element) => { const server = { type: $(element).attr("data-type"), id: $(element).attr("data-id"), serverId: $(element).attr("data-server-id"), name: $(element).find("a.btn").text(), }; return server; }) .get(); const dubServers = $("div.servers-dub .server-item") .map((_, element) => { const server = { type: $(element).attr("data-type"), id: $(element).attr("data-id"), serverId: $(element).attr("data-server-id"), name: $(element).find("a.btn").text(), }; return server; }) .get(); return { sub: subServers, dub: dubServers, }; } async getEpisodeSources(serverId) { const { data } = await axios_1.default.get(`${this.BASE_URL}/ajax/v2/episode/sources?id=${serverId}`); const embedLink = data?.link; if (!embedLink) { throw new Error(`No embed link returned for serverId ${serverId}. Response: ${JSON.stringify(data).slice(0, 200)}...`); } const { data: embedData } = await axios_1.default.get(embedLink, { headers: { Referer: this.BASE_URL, }, }); const $ = cheerio.load(embedData); const dataId = $("div[data-id]").attr("data-id"); let nonce = null; // Try a single 48-char token first const regex48 = /\b[a-zA-Z0-9]{48}\b/; const match48 = embedData.match(regex48); if (match48 && match48[0]) { nonce = match48[0]; } else { // Fallback: concatenate multiple 16-char tokens const regex16 = /"([a-zA-Z0-9]{16})"/g; const parts = []; let m; while ((m = regex16.exec(embedData)) !== null) { if (m[1]) parts.push(m[1]); } if (parts.length) nonce = parts.join(""); } if (!nonce) { throw new Error(`Failed to extract nonce from embed page for serverId ${serverId}`); } const { data: sources } = await axios_1.default.get(`https://megacloud.blog/embed-2/v3/e-1/getSources`, { params: { id: dataId, _k: nonce, }, headers: { Referer: embedLink, }, }); sources.headers = { Referer: "https://megacloud.blog/", }; return sources; } } exports.default = Hianime; //# sourceMappingURL=hianime.js.map