UNPKG

@tiktikimelbo7/extensions

Version:

Nodejs library that provides high-level APIs for obtaining information on various entertainment media such as books, movies, comic books, anime, manga, and so on.

269 lines 13.4 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const cheerio_1 = require("cheerio"); const models_1 = require("../../models"); const utils_1 = require("../../utils"); const utils_2 = require("../../utils"); class Zoro extends models_1.AnimeParser { constructor() { super(...arguments); this.name = 'Zoro'; this.baseUrl = 'https://aniwatch.to'; this.logo = 'https://is3-ssl.mzstatic.com/image/thumb/Purple112/v4/7e/91/00/7e9100ee-2b62-0942-4cdc-e9b93252ce1c/source/512x512bb.jpg'; this.classPath = 'ANIME.Zoro'; /** * @param query Search query * @param page Page number (optional) */ this.search = async (query, page = 1) => { var _a, _b, _c, _d, _e; const res = { currentPage: page, hasNextPage: false, totalPages: 0, results: [], }; try { const { data } = await this.client.get(`${this.baseUrl}/search?keyword=${decodeURIComponent(query)}&page=${page}`); const $ = (0, cheerio_1.load)(data); res.hasNextPage = $('.pagination > li').length > 0 ? $('.pagination li.active').length > 0 ? $('.pagination > li').last().hasClass('active') ? false : true : false : false; res.totalPages = parseInt((_c = (_b = (_a = $('.pagination > .page-item a[title="Last"]')) === null || _a === void 0 ? void 0 : _a.attr('href')) === null || _b === void 0 ? void 0 : _b.split('=').pop()) !== null && _c !== void 0 ? _c : (_e = (_d = $('.pagination > .page-item.active a')) === null || _d === void 0 ? void 0 : _d.text()) === null || _e === void 0 ? void 0 : _e.trim()) || 0; if (res.totalPages === 0 && !res.hasNextPage) res.totalPages = 1; $('.film_list-wrap > div.flw-item').each((i, el) => { var _a; const id = (_a = $(el) .find('div:nth-child(1) > a.film-poster-ahref') .attr('href')) === null || _a === void 0 ? void 0 : _a.split('/')[1].split('?')[0]; const title = $(el).find('div.film-detail > h3.film-name > a.dynamic-name').attr('title'); // Movie, TV, OVA, ONA, Special, Music const type = $(el).find('div:nth-child(2) > div:nth-child(2) > span:nth-child(1)').text(); const image = $(el).find('div:nth-child(1) > img.film-poster-img').attr('data-src'); const url = this.baseUrl + $(el).find('div:nth-child(1) > a').last().attr('href'); res.results.push({ id: id, title: title, type: type.toUpperCase(), image: image, url: url, }); }); if (res.results.length === 0) { res.totalPages = 0; res.hasNextPage = false; } return res; } catch (err) { throw new Error(err); } }; /** * @param id Anime id */ this.fetchAnimeInfo = async (id) => { const info = { id: id, title: '', }; try { const { data } = await this.client.get(`${this.baseUrl}/watch/${id}`); const $ = (0, cheerio_1.load)(data); const { mal_id, anilist_id } = JSON.parse($('#syncData').text()); info.malID = Number(mal_id); info.alID = Number(anilist_id); info.title = $('h2.film-name > a.text-white').text(); info.image = $('img.film-poster-img').attr('src'); info.description = $('div.film-description').text().trim(); // Movie, TV, OVA, ONA, Special, Music info.type = $('span.item').last().prev().prev().text().toUpperCase(); info.url = `${this.baseUrl}/${id}`; const subDub = $('div.film-stats span.item div.tick-dub') .toArray() .map(value => $(value).text().toLowerCase()); if (subDub.length > 1) { info.subOrDub = models_1.SubOrSub.BOTH; } else if (subDub.length > 0) { info.subOrDub = subDub[0]; } else { info.subOrDub = models_1.SubOrSub.SUB; } const episodesAjax = await this.client.get(`${this.baseUrl}/ajax/v2/episode/list/${id.split('-').pop()}`, { headers: { 'X-Requested-With': 'XMLHttpRequest', Referer: `${this.baseUrl}/watch/${id}`, }, }); const $$ = (0, cheerio_1.load)(episodesAjax.data.html); info.totalEpisodes = $$('div.detail-infor-content > div > a').length; info.episodes = []; $$('div.detail-infor-content > div > a').each((i, el) => { var _a, _b, _c, _d; const episodeId = (_c = (_b = (_a = $$(el) .attr('href')) === null || _a === void 0 ? void 0 : _a.split('/')[2]) === null || _b === void 0 ? void 0 : _b.replace('?ep=', '$episode$')) === null || _c === void 0 ? void 0 : _c.concat(`$${info.subOrDub}`); const number = parseInt($$(el).attr('data-number')); const title = $$(el).attr('title'); const url = this.baseUrl + $$(el).attr('href'); const isFiller = $$(el).hasClass('ssl-item-filler'); (_d = info.episodes) === null || _d === void 0 ? void 0 : _d.push({ id: episodeId, number: number, title: title, isFiller: isFiller, url: url, }); }); return info; } catch (err) { throw new Error(err.message); } }; /** * * @param episodeId Episode id */ this.fetchEpisodeSources = async (episodeId, server = models_1.StreamingServers.VidCloud) => { var _a; if (episodeId.startsWith('http')) { const serverUrl = new URL(episodeId); switch (server) { case models_1.StreamingServers.VidStreaming: case models_1.StreamingServers.VidCloud: return Object.assign({}, (await new utils_1.RapidCloud(this.proxyConfig, this.adapter).extract(serverUrl))); case models_1.StreamingServers.StreamSB: return { headers: { Referer: serverUrl.href, watchsb: 'streamsb', 'User-Agent': utils_2.USER_AGENT }, sources: await new utils_1.StreamSB(this.proxyConfig, this.adapter).extract(serverUrl, true), }; case models_1.StreamingServers.StreamTape: return { headers: { Referer: serverUrl.href, 'User-Agent': utils_2.USER_AGENT }, sources: await new utils_1.StreamTape(this.proxyConfig, this.adapter).extract(serverUrl), }; default: case models_1.StreamingServers.VidCloud: return Object.assign({ headers: { Referer: serverUrl.href } }, (await new utils_1.RapidCloud(this.proxyConfig, this.adapter).extract(serverUrl))); } } if (!episodeId.includes('$episode$')) throw new Error('Invalid episode id'); // Fallback to using sub if no info found in case of compatibility // TODO: add both options later const subOrDub = ((_a = episodeId.split('$')) === null || _a === void 0 ? void 0 : _a.pop()) === 'dub' ? 'dub' : 'sub'; episodeId = `${this.baseUrl}/watch/${episodeId .replace('$episode$', '?ep=') .replace(/\$auto|\$sub|\$dub/gi, '')}`; try { const { data } = await this.client.get(`${this.baseUrl}/ajax/v2/episode/servers?episodeId=${episodeId.split('?ep=')[1]}`); const $ = (0, cheerio_1.load)(data.html); /** * vidtreaming -> 4 * rapidcloud -> 1 * streamsb -> 5 * streamtape -> 3 */ let serverId = ''; try { switch (server) { case models_1.StreamingServers.VidCloud: serverId = this.retrieveServerId($, 1, subOrDub); // zoro's vidcloud server is rapidcloud if (!serverId) throw new Error('RapidCloud not found'); break; case models_1.StreamingServers.VidStreaming: serverId = this.retrieveServerId($, 4, subOrDub); // zoro's vidcloud server is rapidcloud if (!serverId) throw new Error('vidtreaming not found'); break; case models_1.StreamingServers.StreamSB: serverId = this.retrieveServerId($, 5, subOrDub); if (!serverId) throw new Error('StreamSB not found'); break; case models_1.StreamingServers.StreamTape: serverId = this.retrieveServerId($, 3, subOrDub); if (!serverId) throw new Error('StreamTape not found'); break; } } catch (err) { throw new Error("Couldn't find server. Try another server"); } const { data: { link }, } = await this.client.get(`${this.baseUrl}/ajax/v2/episode/sources?id=${serverId}`); return await this.fetchEpisodeSources(link, server); } catch (err) { throw err; } }; this.retrieveServerId = ($, index, subOrDub) => { return $(`div.ps_-block.ps_-block-sub.servers-${subOrDub} > div.ps__-list > div`) .map((i, el) => ($(el).attr('data-server-id') == `${index}` ? $(el) : null)) .get()[0] .attr('data-id'); }; /** * @param page Page number */ this.fetchRecentEpisodes = async (page = 1) => { try { const { data } = await this.client.get(`${this.baseUrl}/recently-updated?page=${page}`); const $ = (0, cheerio_1.load)(data); const hasNextPage = $('.pagination > li').length > 0 ? $('.pagination > li').last().hasClass('active') ? false : true : false; const recentEpisodes = []; $('div.film_list-wrap > div').each((i, el) => { var _a; recentEpisodes.push({ id: (_a = $(el).find('div.film-poster > a').attr('href')) === null || _a === void 0 ? void 0 : _a.replace('/', ''), image: $(el).find('div.film-poster > img').attr('data-src'), title: $(el).find('div.film-poster > img').attr('alt'), url: `${this.baseUrl}${$(el).find('div.film-poster > a').attr('href')}`, episode: parseInt($(el).find('div.tick-eps').text().replace(/\s/g, '').replace('Ep', '').split('/')[0]), }); }); return { currentPage: page, hasNextPage: hasNextPage, results: recentEpisodes, }; } catch (err) { throw new Error('Something went wrong. Please try again later.'); } }; /** * @deprecated * @param episodeId Episode id */ this.fetchEpisodeServers = (episodeId) => { throw new Error('Method not implemented.'); }; } } // (async () => { // const zoro = new Zoro(); // const anime = await zoro.search('classroom of the elite'); // const info = await zoro.fetchAnimeInfo(anime.results[0].id); // const sources = await zoro.fetchEpisodeSources(info.episodes![0].id); // console.log(sources); // })(); exports.default = Zoro; //# sourceMappingURL=zoro.js.map