const cloudscraper = require('cloudscraper') const cheerio = require('cheerio'); const base64 = require('node-base64-image'); const { BASE_ANIMEFLV, BASE_JIKAN, BASE_EPISODE_IMG_URL, SEARCH_URL } = require('../api/urls'); const animeflvInfo = async (id, index) =>{ try{ const res = await cloudscraper(`${BASE_ANIMEFLV}anime/${id}`); const body = await res; const $ = cheerio.load(body); const scripts = $('script'); const anime_info_ids = []; const anime_eps_data = []; const animeExtraInfo = []; const genres = []; let listByEps; let poster = `${BASE_ANIMEFLV}` + $('body div div div div div aside div.AnimeCover div.Image figure img').attr('src') const banner = poster.replace('covers' , 'banners').trim(); let synopsis = $('body div div div div div main section div.Description p').text().trim(); let rating = $('body div div div.Ficha.fchlt div.Container div.vtshr div.Votes span#votes_prmd').text(); const debut = $('body div.Wrapper div.Body div div.Container div.BX.Row.BFluid.Sp20 aside.SidebarA.BFixed p.AnmStts').text(); const type = $('body div.Wrapper div.Body div div.Ficha.fchlt div.Container span.Type').text() animeExtraInfo.push({ poster: poster, banner: banner, synopsis: synopsis, rating: rating, debut: debut, type: type, }) $('main.Main section.WdgtCn nav.Nvgnrs a').each((index , element) =>{ const $element = $(element); const genre = $element.attr('href').split('=')[1] || null; genres.push(genre); }); Array.from({length: scripts.length} , (v , k) =>{ const $script = $(scripts[k]); const contents = $script.html(); if((contents || '').includes('var anime_info = [')) { let anime_info = contents.split('var anime_info = ')[1].split(';\n')[0]; let dat_anime_info = JSON.parse(anime_info); anime_info_ids.push(dat_anime_info); } if((contents || '').includes('var episodes = [')) { let episodes = contents.split('var episodes = ')[1].split(';')[0]; let eps_data = JSON.parse(episodes) anime_eps_data.push(eps_data); } }); const AnimeThumbnailsId = index; const animeId = id; let nextEpisodeDate = anime_info_ids[0][3] || null; const amimeTempList = []; for(const [key , value] of Object.entries(anime_eps_data)){ let episode = anime_eps_data[key].map(x => x[0]); let episodeId = anime_eps_data[key].map(x => x[1]); amimeTempList.push(episode , episodeId); } const animeListEps = [{nextEpisodeDate: nextEpisodeDate}]; Array.from({length: amimeTempList[1].length} , (v , k) =>{ let data = amimeTempList.map(x => x[k]); let episode = data[0]; let id = data[1]; let imagePreview = `${BASE_EPISODE_IMG_URL}${AnimeThumbnailsId}/${episode}/th_3.jpg` let link = `${id}/${animeId}-${episode}` animeListEps.push({ episode: episode, id: link, imagePreview: imagePreview }) }) listByEps = animeListEps; return {listByEps , genres , animeExtraInfo}; }catch(err){ console.error(err) } }; const getAnimeCharacters = async(title) =>{ const res = await cloudscraper(`${BASE_JIKAN}search/anime?q=${title}`); const matchAnime = JSON.parse(res).results.filter(x => x.title === title); const malId = matchAnime[0].mal_id; if(typeof matchAnime[0].mal_id === 'undefined') return null; const jikanCharactersURL = `${BASE_JIKAN}anime/${malId}/characters_staff`; const data = await cloudscraper.get(jikanCharactersURL); let body = JSON.parse(data).characters; if(typeof body === 'undefined') return null; const charactersId = body.map(doc =>{ return doc.mal_id }) const charactersNames = body.map(doc => { return doc.name; }); const charactersImages = body.map(doc =>{ return doc.image_url }); let characters = []; Array.from({length: charactersNames.length} , (v , k) =>{ const id = charactersId[k]; let name = charactersNames[k]; let characterImg = charactersImages[k]; characters.push({ id: id, name: name, image: characterImg }); }); return Promise.all(characters); }; const getAnimeVideoPromo = async(title) =>{ const res = await cloudscraper(`${BASE_JIKAN}search/anime?q=${title}`); const matchAnime = JSON.parse(res).results.filter(x => x.title === title); const malId = matchAnime[0].mal_id; if(typeof matchAnime[0].mal_id === 'undefined') return null; const jikanCharactersURL = `${BASE_JIKAN}anime/${malId}/videos`; const data = await cloudscraper.get(jikanCharactersURL); const body = JSON.parse(data).promo; const promises = []; body.map(doc =>{ promises.push({ title: doc.title, previewImage: doc.image_url, videoURL: doc.video_url }); }); return Promise.all(promises); }; const animeExtraInfo = async(title) =>{ const res = await cloudscraper(`${BASE_JIKAN}search/anime?q=${title}`); const matchAnime = JSON.parse(res).results.filter(x => x.title === title); const malId = matchAnime[0].mal_id; if(typeof matchAnime[0].mal_id === 'undefined') return null; const animeDetails = `${BASE_JIKAN}anime/${malId}`; const data = await cloudscraper.get(animeDetails); const body = Array(JSON.parse(data)); const promises = []; body.map(doc =>{ let airDay switch (doc.broadcast.split('at')[0].replace(" ", "").toLowerCase()) { case "mondays": airDay = "Lunes"; break; case "monday": airDay = "Lunes"; break; case "tuesdays": airDay = "Martes"; break; case "tuesday": airDay = "Martes"; break; case "wednesdays": airDay = "Miércoles"; break; case "wednesday": airDay = "Miércoles"; break; case "thursdays": airDay = "Jueves"; break; case "thursday": airDay = "Jueves"; break; case "fridays": airDay = "Viernes"; break; case "friday": airDay = "Viernes"; break; case "saturdays": airDay = "Sábados"; break; case "saturday": airDay = "Sábados"; break; case "sundays": airDay = "Domingos"; break; case "sunday": airDay = "Domingos"; break; default: airDay = "Sin emisión"; } promises.push({ titleJapanese: doc.title_japanese, source: doc.source, totalEpisodes: doc.episodes, aired:{ from: doc.aired.from, to: doc.aired.to }, duration: doc.duration.split('per')[0].replace(" ", ""), rank: doc.rank, broadcast: airDay, producers: doc.producers.map(x => x.name) || null, licensors: doc.licensors.map(x => x.name) || null, studios: doc.studios.map(x => x.name) || null, openingThemes: doc.opening_themes || null, endingThemes: doc.ending_themes || null }); }); return Promise.all(promises); }; const imageUrlToBase64 = async(url) => { return await base64.encode(url, {string:true}); }; const search = async() =>{ } const searchAnime = async(query) => { const res = await cloudscraper(`${SEARCH_URL}${query}`); const body = await res; const $ = cheerio.load(body); const promises = []; $('div.Container ul.ListAnimes li article').each((index , element) =>{ const $element = $(element); const id = $element.find('div.Description a.Button').attr('href').slice(1); const title = $element.find('a h3').text(); let poster = $element.find('a div.Image figure img').attr('src') || $element.find('a div.Image figure img').attr('data-cfsrc'); const type = $element.find('div.Description p span.Type').text(); promises.push(search().then(async extra => ({ id: id || null, title: title || null, type: type || null, image: await imageUrlToBase64(poster) || null }))); }) return Promise.all(promises); }; const transformUrlServer = async(urlReal) =>{ let res let body const promises = [] for(i = 0; i <= urlReal.length -1; i++){ switch (urlReal[i].server) { case "amus": res = await cloudscraper(urlReal[i].code.replace("embed","check")); body = await res; urlReal[i].code = JSON.parse(body).file urlReal[i].direct = true break; case "natsuki": res = await cloudscraper(urlReal[i].code.replace("embed","check")); body = await res; urlReal[i].code = JSON.parse(body).file urlReal[i].direct = true break; default: urlReal[i].direct = false break; } } urlReal.map(doc =>{ promises.push({ id: doc.title.toLowerCase(), url: doc.code, direct: doc.direct }); }); return promises; } const obtainPreviewNews = (encoded) => { let image; if (encoded.includes('