UNPKG

consumet.custom

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.

366 lines 17.5 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const cheerio_1 = require("cheerio"); const models_1 = require("../../models"); const extractors_1 = require("../../extractors"); class Anix extends models_1.AnimeParser { constructor(customBaseURL, proxy, adapter) { super(proxy, adapter); this.name = 'Anix'; this.baseUrl = 'https://anix.sh'; this.logo = 'https://anix.sh/img/logo.png'; this.classPath = 'ANIME.Anix'; this.defaultSort = `&type%5B%5D=1&type%5B%5D=5&type%5B%5D=3&type%5B%5D=4&type%5B%5D=2&type%5B%5D=7&status[]=${models_1.MediaStatus.ONGOING}&status[]=${models_1.MediaStatus.COMPLETED}`; this.requestedWith = 'XMLHttpRequest'; /** * @param page page number (optional) */ this.fetchRecentEpisodes = async (page = 1) => { try { const res = await this.client.get(`${this.baseUrl}/filter?${this.defaultSort}&sort=recently_updated&page=${page}`); const $ = (0, cheerio_1.load)(res.data); const recentEpisodes = []; $('.basic.ani.content-item .piece').each((i, el) => { const poster = $(el).find('a.poster'); const url = $(poster).attr('href'); const episodeNum = parseFloat($(el).find('.sub').text()); const type = $(el).find('.type.dot').text(); let finalType = models_1.MediaFormat.TV; switch (type) { case 'ONA': finalType = models_1.MediaFormat.ONA; break; case 'Movie': finalType = models_1.MediaFormat.MOVIE; break; case 'OVA': finalType = models_1.MediaFormat.OVA; break; case 'Special': finalType = models_1.MediaFormat.SPECIAL; break; case 'Music': finalType = models_1.MediaFormat.MUSIC; break; case 'PV': finalType = models_1.MediaFormat.PV; break; case 'TV Special': finalType = models_1.MediaFormat.TV_SPECIAL; break; case 'Comic': finalType = models_1.MediaFormat.COMIC; break; } recentEpisodes.push({ id: url === null || url === void 0 ? void 0 : url.split('/')[2], episodeId: `ep-${episodeNum}`, episodeNumber: episodeNum, title: $(el).find('.d-title').text(), englishTitle: $(el).find('.d-title').attr('data-en'), image: $(poster).find('img').attr('src'), url: `${this.baseUrl.trim()}${url === null || url === void 0 ? void 0 : url.trim()}`, type: finalType, }); }); const hasNextPage = !$('.pagination li').last().hasClass('active'); return { currentPage: page, hasNextPage: hasNextPage, results: recentEpisodes, }; } catch (err) { throw new Error('Something went wrong. Please try again later.'); } }; /** * @param query Search query * @param page Page number (optional) */ this.search = async (query, page = 1) => { try { const res = await this.client.get(`${this.baseUrl}/filter?keyword=${query}&page=${page}&${this.defaultSort}`); const $ = (0, cheerio_1.load)(res.data); let hasNextPage = $('.pagination').length > 0; if (hasNextPage) { hasNextPage = !$('.pagination li').last().hasClass('active'); } const searchResult = { currentPage: page, hasNextPage: hasNextPage, results: [], }; $('.basic.ani.content-item .piece').each((i, el) => { const poster = $(el).find('a.poster'); const url = $(poster).attr('href'); const type = $(el).find('.type.dot').text(); let finalType = models_1.MediaFormat.TV; switch (type) { case 'ONA': finalType = models_1.MediaFormat.ONA; break; case 'Movie': finalType = models_1.MediaFormat.MOVIE; break; case 'OVA': finalType = models_1.MediaFormat.OVA; break; case 'Special': finalType = models_1.MediaFormat.SPECIAL; break; case 'Music': finalType = models_1.MediaFormat.MUSIC; break; case 'PV': finalType = models_1.MediaFormat.PV; break; case 'TV Special': finalType = models_1.MediaFormat.TV_SPECIAL; break; case 'Comic': finalType = models_1.MediaFormat.COMIC; break; } searchResult.results.push({ id: url === null || url === void 0 ? void 0 : url.split('/')[2], title: $(el).find('.d-title').text(), englishTitle: $(el).find('.d-title').attr('data-en'), image: $(poster).find('img').attr('src'), url: `${this.baseUrl.trim()}${url === null || url === void 0 ? void 0 : url.trim()}`, type: finalType, }); }); return searchResult; } catch (err) { throw new Error(err.message); } }; /** * @param id Anime id */ this.fetchAnimeInfo = async (id) => { var _a, _b, _c, _d; const url = `${this.baseUrl}/anime/${id}/ep-1`; try { const res = await this.client.get(url); const $ = (0, cheerio_1.load)(res.data); const animeInfo = { id: id, title: (_a = $('.ani-data .maindata .ani-name.d-title')) === null || _a === void 0 ? void 0 : _a.text().trim(), englishTitle: (_c = (_b = $('.ani-data .maindata .ani-name.d-title')) === null || _b === void 0 ? void 0 : _b.attr('data-en')) === null || _c === void 0 ? void 0 : _c.trim(), url: `${this.baseUrl}/anime/${id}`, image: (_d = $('.ani-data .poster img')) === null || _d === void 0 ? void 0 : _d.attr('src'), description: $('.ani-data .maindata .description .cts-block div').text().trim(), episodes: [], }; $('.episodes .ep-range').each((i, el) => { $(el) .find('div') .each((i, el) => { var _a, _b, _c; (_a = animeInfo.episodes) === null || _a === void 0 ? void 0 : _a.push({ id: (_b = $(el).find('a').attr('href')) === null || _b === void 0 ? void 0 : _b.split('/')[3], number: parseFloat($(el).find(`a`).text()), url: `${this.baseUrl}${(_c = $(el).find(`a`).attr('href')) === null || _c === void 0 ? void 0 : _c.trim()}`, }); }); }); const metaData = { status: '', type: '' }; $('.metadata .limiter div').each((i, el) => { var _a; const text = $(el).text().trim(); if (text.includes('Genre: ')) { $(el) .find('span a') .each((i, el) => { if (animeInfo.genres == undefined) { animeInfo.genres = []; } animeInfo.genres.push($(el).attr('title')); }); } else if (text.includes('Status: ')) { metaData.status = text.replace('Status: ', ''); } else if (text.includes('Type: ')) { metaData.type = text.replace('Type: ', ''); } else if (text.includes('Episodes: ')) { animeInfo.totalEpisodes = (_a = parseFloat(text.replace('Episodes: ', ''))) !== null && _a !== void 0 ? _a : undefined; } else if (text.includes('Country: ')) { animeInfo.countryOfOrigin = text.replace('Country: ', ''); } }); animeInfo.status = models_1.MediaStatus.UNKNOWN; switch (metaData.status) { case 'Ongoing': animeInfo.status = models_1.MediaStatus.ONGOING; break; case 'Completed': animeInfo.status = models_1.MediaStatus.COMPLETED; break; } animeInfo.type = models_1.MediaFormat.TV; switch (metaData.type) { case 'ONA': animeInfo.type = models_1.MediaFormat.ONA; break; case 'Movie': animeInfo.type = models_1.MediaFormat.MOVIE; break; case 'OVA': animeInfo.type = models_1.MediaFormat.OVA; break; case 'Special': animeInfo.type = models_1.MediaFormat.SPECIAL; break; case 'Music': animeInfo.type = models_1.MediaFormat.MUSIC; break; case 'PV': animeInfo.type = models_1.MediaFormat.PV; break; case 'TV Special': animeInfo.type = models_1.MediaFormat.TV_SPECIAL; break; case 'Comic': animeInfo.type = models_1.MediaFormat.COMIC; break; } return animeInfo; } catch (err) { throw new Error(err.message); } }; /** * * @param id Anime id * @param episodeId Episode id * @param server Streaming server(optional) */ this.fetchEpisodeSources = async (id, episodeId, server = models_1.StreamingServers.BuiltIn) => { var _a; const url = `${this.baseUrl}/anime/${id}/${episodeId}`; const uri = new URL(url); const res = await this.client.get(url); const $ = (0, cheerio_1.load)(res.data); const servers = new Map(); $($('.ani-server-type-pad')[0]) .find('.server') .each((i, el) => { servers.set($(el).text().trim(), $(el).attr('data-video')); }); switch (server) { case models_1.StreamingServers.Mp4Upload: if (servers.get('Mp4upload') !== undefined) { const streamUri = new URL(servers.get('Mp4upload')); return { headers: { Referer: uri.origin, }, ...(await new extractors_1.StreamWish(this.proxyConfig, this.adapter).extract(streamUri)), }; } throw new Error('Mp4Upload server not found'); case models_1.StreamingServers.StreamWish: const streamUrl = (_a = servers.get('Streamwish')) !== null && _a !== void 0 ? _a : undefined; if (servers.get('Streamwish') != undefined) { const streamUri = new URL(servers.get('Streamwish')); return { headers: { Referer: uri.origin, }, ...(await new extractors_1.StreamWish(this.proxyConfig, this.adapter).extract(streamUri)), }; } throw new Error('StreamWish server not found'); default: const episodeSources = { sources: [], }; try { let defaultUrl = ''; $('script:contains("loadIframePlayer")').each((i, el) => { const scriptContent = $(el).text(); // Regular expression to capture the JSON inside loadIframePlayer const jsonRegex = /loadIframePlayer\(\s*(['"`])(\[[\s\S]*?\])\1/; const match = jsonRegex.exec(scriptContent); if (match && match[0]) { const extractedJson = match[0] .replace('loadIframePlayer(', '') .replace("'", '') .replace("'", ''); const data = JSON.parse(extractedJson); defaultUrl = data[0].url; episodeSources.sources.push({ url: defaultUrl, quality: `default`, isM3U8: true, }); } else { console.error('No JSON data found in loadIframePlayer call.'); } }); const m3u8Content = await this.client.get(defaultUrl); if (m3u8Content.data.includes('EXTM3U')) { const videoList = m3u8Content.data.split('#EXT-X-STREAM-INF:'); for (const video of videoList !== null && videoList !== void 0 ? videoList : []) { if (video.includes('BANDWIDTH')) { const url = video.split('\n')[1]; const quality = video.split('RESOLUTION=')[1].split('\n')[0].split('x')[1]; const path = defaultUrl.replace(/\/[^/]*\.m3u8$/, '/'); episodeSources.sources.push({ url: path + url, quality: `${quality.split(',')[0]}p`, isM3U8: true, }); } } } } catch (err) { throw new Error(err.message); } return { headers: { Referer: uri.origin, }, ...episodeSources, }; } }; /** * * @param id Anime id * @param episodeId Episode id */ this.fetchEpisodeServers = async (id, episodeId) => { const url = `${this.baseUrl}/anime/${id}/${episodeId}`; const uri = new URL(url); const res = await this.client.get(url); const $ = (0, cheerio_1.load)(res.data); const servers = []; $($('.ani-server-type-pad')[0]) .find('.server') .each((i, el) => { servers.push({ name: $(el).text().trim(), url: $(el).attr('data-video'), }); }); return servers; }; this.baseUrl = customBaseURL ? customBaseURL.startsWith('http://') || customBaseURL.startsWith('https://') ? customBaseURL : `http://${customBaseURL}` : this.baseUrl; } } exports.default = Anix; //# sourceMappingURL=anix.js.map