v2.6.0 - Obtain More Data

pull/1/head v2.6.0
Jéluchu 5 years ago
parent bc868b71cd
commit b07d16d33d

@ -1,4 +1,4 @@
# **Aruppi API** (v2.5.0)
# **Aruppi API** (v2.6.0)
> This API has everything about Japan, from anime, music, radio, images, videos ... to japanese culture
>

7
package-lock.json generated

@ -1,6 +1,6 @@
{
"name": "aruppi",
"version": "2.4.0",
"version": "2.5.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
@ -1162,6 +1162,11 @@
"nan": "^2.13.2"
}
},
"node-fetch": {
"version": "2.6.0",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.0.tgz",
"integrity": "sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA=="
},
"normalize-url": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.0.tgz",

@ -1,6 +1,6 @@
{
"name": "aruppi",
"version": "2.5.0",
"version": "2.6.0",
"description": "Aruppi is a custom API to obtain data from the Japanese culture for the mobile app",
"main": "./src/api/api.js",
"scripts": {
@ -51,6 +51,7 @@
"helmet": "^3.23.3",
"hooman": "^1.2.5",
"rss-to-json": "^1.1.1",
"tough-cookie": "^4.0.0"
"tough-cookie": "^4.0.0",
"node-fetch": "^2.6.0"
}
}

@ -5,6 +5,7 @@ const {
} = require('../api/apiCall');
const {
jkanimeInfo,
animeflvInfo,
imageUrlToBase64,
getAnimeCharacters,
@ -16,7 +17,8 @@ const {
structureThemes,
getAnimes,
getDirectory,
helper
helper,
videoServersJK
} = require('../utils/index');
const ThemeParser = require('../utils/animetheme');
@ -256,10 +258,29 @@ const getMoreInfo = async (title) =>{
let seriesTitle
let position
const jkAnimeTitles = [
{ title: 'The God of High School', id: 'the-god-of-high-school' },
{ title: 'Kami no Tou', id: 'kami-no-tou' },
{ title: 'BNA', id: 'bna' }
];
let jkanime = false
let jkanimeID
let jkanimeName
for (let name in jkAnimeTitles) {
if (title === jkAnimeTitles[name].title) {
jkanime = true
jkanimeID = jkAnimeTitles[name].id
jkanimeName = jkAnimeTitles[name].title
}
}
if (jkanime === false) {
const titles = [
{ animeflv: 'Kaguya-sama wa Kokurasetai: Tensai-tachi no Renai Zunousen 2nd Season', myanimelist: 'Kaguya-sama wa Kokurasetai?: Tensai-tachi no Renai Zunousen', alternative: 'Kaguya-sama wa Kokurasetai'},
{ animeflv: 'Naruto Shippuden', myanimelist: 'Naruto: Shippuuden' },
{ animeflv: 'Rock Lee no Seishun Full-Power Ninden', myanimelist: 'Naruto SD: Rock Lee no Seishun Full-Power Ninden' }
{ animeflv: 'Rock Lee no Seishun Full-Power Ninden', myanimelist: 'Naruto SD: Rock Lee no Seishun Full-Power Ninden' },
{ animeflv: 'BAKI: dai reitaisai-hen', myanimelist: 'Baki 2nd Season' }
];
for (let name in titles) {
@ -331,6 +352,27 @@ const getMoreInfo = async (title) =>{
}catch(err){
console.log(err)
}
} else {
promises.push(await jkanimeInfo(jkanimeID).then(async extra => ({
title: jkanimeName || null,
poster: await imageUrlToBase64(extra.animeExtraInfo[0].poster) || null,
synopsis: extra.animeExtraInfo[0].synopsis || null,
status: extra.animeExtraInfo[0].debut || null,
type: extra.animeExtraInfo[0].type || null,
rating: extra.animeExtraInfo[0].rating || null,
genres: extra.genres || null,
episodes: extra.listByEps || null,
moreInfo: await animeExtraInfo(jkanimeName).then(info =>{
return info || null
}),
promo: await getAnimeVideoPromo(jkanimeName).then(promo =>{
return promo || null
}),
characters: await getAnimeCharacters(jkanimeName).then(characters =>{
return characters || null
})
})));
}
return promises;
@ -338,12 +380,33 @@ const getMoreInfo = async (title) =>{
const getAnimeServers = async (id) => {
const jkAnimeIDs = [
{ id: 'the-god-of-high-school' },
{ id: 'kami-no-tou' },
{ id: 'bna' }
];
let jkanime = false
let jkanimeID
for (let name in jkAnimeIDs) {
if (id.includes(jkAnimeIDs[name].id)) {
jkanime = true
jkanimeID = id
}
}
if (jkanime === false) {
let options = { parse: true }
const data = await homgot(`${BASE_ANIMEFLV_JELU}GetAnimeServers/${id}`, options);
let body = data.servers;
return await transformUrlServer(body);
} else {
return await videoServersJK(jkanimeID)
}
};
const search = async (title) =>{ return await searchAnime(title); };

@ -7,7 +7,7 @@ router.get('/', (req, res) => {
res.json({
message: 'Aruppi API - 🎏',
author: 'Jéluchu',
version: '2.5.0',
version: '2.6.0',
credits: 'The bitch loves APIs that offers data to Aruppi App',
entries: [
{

@ -1,6 +1,7 @@
module.exports = {
BASE_ARUPPI: 'https://aruppi.jeluchu.xyz/',
BASE_ANIMEFLV: 'https://animeflv.net/',
BASE_JKANIME: 'https://jkanime.net/',
BASE_ANIMEFLV_JELU: 'https://aruppi.jeluchu.xyz/apis/animeflv/v1/',
BASE_YOUTUBE: 'https://aruppi.jeluchu.xyz/apis/youtube/v3/search?channelId=',
BASE_JIKAN: 'https://aruppi.jeluchu.xyz/apis/jikan/v3/',
@ -10,6 +11,7 @@ module.exports = {
BASE_RAMENPARADOS: 'https://ramenparados.com/category/noticias/anime/feed/',
BASE_CRUNCHYROLL: 'https://www.crunchyroll.com/newsrss?lang=esES',
SEARCH_URL: 'https://animeflv.net/browse?q=',
JKANIME_URL: 'https://jkanime.net/buscar/',
GENRES_URL: 'https://animeflv.net/browse?',
SEARCH_DIRECTORY: 'https://animeflv.net/browse?order=title&page=',
BASE_EPISODE_IMG_URL: 'https://cdn.animeflv.net/screenshots/',

@ -0,0 +1,42 @@
[
{ "name": " Acción", "value": "accion" },
{ "name": " Artes Marciales", "value": "artes-marciales" },
{ "name": " Aventuras", "value": "aventura" },
{ "name": " Carreras", "value": "carreras" },
{ "name": " Ciencia Ficción", "value": "ciencia-ficcion" },
{ "name": " Comedia", "value": "comedia" },
{ "name": " Demencia", "value": "demencia" },
{ "name": " Demonios", "value": "demonios" },
{ "name": " Deportes", "value": "deportes" },
{ "name": " Drama", "value": "drama" },
{ "name": " Ecchi", "value": "ecchi" },
{ "name": " Escolares", "value": "escolares" },
{ "name": " Espacial", "value": "espacial" },
{ "name": " Fantasía", "value": "fantasia" },
{ "name": " Harem", "value": "harem" },
{ "name": " Historico", "value": "historico" },
{ "name": " Infantil", "value": "infantil" },
{ "name": " Josei", "value": "josei" },
{ "name": " Juegos", "value": "juegos" },
{ "name": " Magia", "value": "magia" },
{ "name": " Mecha", "value": "mecha" },
{ "name": " Militar", "value": "militar" },
{ "name": " Misterio", "value": "misterio" },
{ "name": " Música", "value": "musica" },
{ "name": " Parodia", "value": "parodia" },
{ "name": " Policía", "value": "policia" },
{ "name": " Psicológico", "value": "psicologico" },
{ "name": " Recuentos de la vida", "value": "recuentos-de-la-vida" },
{ "name": " Romance", "value": "romance" },
{ "name": " Samurai", "value": "samurai" },
{ "name": " Seinen", "value": "seinen" },
{ "name": " Shoujo", "value": "shoujo" },
{ "name": " Shounen", "value": "shounen" },
{ "name": " Sobrenatural", "value": "sobrenatural" },
{ "name": " Superpoderes", "value": "superpoderes" },
{ "name": " Suspenso", "value": "suspenso" },
{ "name": " Terror", "value": "terror" },
{ "name": " Vampiros", "value": "vampiros" },
{ "name": " Yaoi", "value": "yaoi" },
{ "name": " Yuri", "value": "yuri" }
]

@ -1,11 +1,185 @@
const {
BASE_ANIMEFLV, BASE_JIKAN, BASE_EPISODE_IMG_URL, SEARCH_URL, SEARCH_DIRECTORY, BASE_ARUPPI
BASE_ANIMEFLV, BASE_JIKAN, BASE_EPISODE_IMG_URL, SEARCH_URL, SEARCH_DIRECTORY, BASE_ARUPPI, BASE_JKANIME, JKANIME_URL
} = require('../api/urls');
const {
homgot
} = require('../api/apiCall');
function btoa(str) {
let buffer;
if (str instanceof Buffer) {
buffer = str;
}
else {
buffer = Buffer.from(str.toString(), 'binary');
}
return buffer.toString('base64');
}
global.btoa = btoa;
async function videoServersJK(id) {
let options = { scrapy: true }
const $ = await homgot(`${BASE_JKANIME}${id}`, options);
const scripts = $('script');
const totalEps = $('div#container div#reproductor-box div ul li').length;
const serverNames = [];
let servers = [];
$('div#container div#reproductor-box div ul li').each((index , element) =>{
const $element = $(element);
const serverName = $element.find('a').text();
serverNames.push(serverName);
})
for(let i = 0; i < scripts.length; i++){
const $script = $(scripts[i]);
const contents = $script.html();
try{
if ((contents || '').includes('var video = [];')) {
Array.from({length: totalEps} , (v , k) =>{
let index = Number(k + 1);
let videoPageURL = contents.split(`video[${index}] = \'<iframe class="player_conte" src="`)[1].split('"')[0];
servers.push({iframe: videoPageURL});
});
}
}catch(err) {
return null;
}
}
let serverList = [];
let serverTempList = [];
for(const [key , value] of Object.entries(servers)) {
let video = await getVideoURL(value.iframe)
serverTempList.push(video);
}
Array.from({length: serverTempList.length} , (v , k) =>{
let name = serverNames[k];
let video = serverTempList[k];
serverList.push({server: name, video: video});
});
serverList = serverList.filter(function( obj ) {
return obj.server !== 'Xtreme S';
});
return await Promise.all(serverList);
}
async function getVideoURL(url) {
let options = { scrapy: true }
const $ = await homgot(url, options);
const video = $('video');
if(video.length){
const src = $(video).find('source').attr('src');
return src || null;
}
else{
const scripts = $('script');
const l = global;
const ll = String;
const $script2 = $(scripts[1]).html();
eval($script2);
return l.ss || null;
}
}
const jkanimeInfo = async (id) => {
let poster = ""
let banner = ""
let synopsis = ""
let rating = ""
let debut = ""
let type = ""
let $
try {
let options = { scrapy: true }
$ = await homgot(`${BASE_JKANIME}${id}`, options);
const animeExtraInfo = [];
const genres = [];
let listByEps;
poster = $('div[id="container"] div.serie-info div.cap-portada')[0].children[1].attribs.src;
banner = $('div[id="container"] div.serie-info div.cap-portada')[0].children[1].attribs.src;
synopsis = $('div[id="container"] div.serie-info div.sinopsis-box p')[0].children[1].data;
rating = "Sin calificación"
debut = $('div[id="container"] div.serie-info div.info-content div')[6].children[3].children[0].children[0].data;
type = $('div[id="container"] div.serie-info div.info-content div')[0].children[3].children[0].data
animeExtraInfo.push({
poster: poster,
banner: banner,
synopsis: synopsis,
rating: rating,
debut: debut,
type: type,
})
let rawGenres = $('div[id="container"] div.serie-info div.info-content div')[1].children[3].children
for (let i = 0; i <= rawGenres.length -1; i++) {
if (rawGenres[i].name === 'a') {
const genre = rawGenres[i].children[0].data
genres.push(genre)
}
}
let nextEpisodeDate
let rawNextEpisode = $('div[id="container"] div.left-container div[id="proxep"] p')[0]
if (rawNextEpisode === undefined) {
nextEpisodeDate = null
} else {
if (rawNextEpisode.children[1].data === ' ') {
nextEpisodeDate = null
} else {
nextEpisodeDate = rawNextEpisode
}
}
const eps_temp_list = [];
let episodes_aired = '';
$('div#container div.left-container div.navigation a').each(async(index , element) => {
const $element = $(element);
const total_eps = $element.text();
eps_temp_list.push(total_eps);
})
try{episodes_aired = eps_temp_list[0].split('-')[1].trim();}catch(err){}
const animeListEps = [{nextEpisodeDate: nextEpisodeDate}];
for (let i = 0; i <= episodes_aired; i++) {
let episode = i;
let animeId = $('div[id="container"] div.content-box div[id="episodes-content"]')[0].children[1].children[3].attribs.src.split('/')[7].split('.jpg')[0];
let imagePreview = $('div[id="container"] div.content-box div[id="episodes-content"]')[0].children[1].children[3].attribs.src
let link = `${animeId}/${episode}`
animeListEps.push({
episode: episode,
id: link,
imagePreview: imagePreview
})
}
listByEps = animeListEps;
return {listByEps, genres, animeExtraInfo};
} catch (err) {
console.error(err)
}
};
const animeflvInfo = async (id, index) => {
let poster = ""
@ -205,6 +379,13 @@ const animeExtraInfo = async (title) => {
'default': 'Sin emisión'
};
let broadcast
if (doc.broadcast === null) {
broadcast = null
} else {
broadcast = airDay[doc.broadcast.split('at')[0].replace(" ", "").toLowerCase()]
}
promises.push({
titleJapanese: doc.title_japanese,
source: doc.source,
@ -215,7 +396,7 @@ const animeExtraInfo = async (title) => {
},
duration: doc.duration.split('per')[0],
rank: doc.rank,
broadcast: airDay[doc.broadcast.split('at')[0].replace(" ", "").toLowerCase()],
broadcast: broadcast,
producers: doc.producers.map(x => x.name) || null,
licensors: doc.licensors.map(x => x.name) || null,
studios: doc.studios.map(x => x.name) || null,
@ -238,6 +419,21 @@ const searchAnime = async (query) => {
let $
let promises = []
const jkAnimeTitles = [
{ title: 'BNA', search: 'BNA'},
{ title: 'The God of High School', search: 'The god' }
];
let jkanime = false
let jkanimeName
for (let name in jkAnimeTitles) {
if (query === jkAnimeTitles[name].title) {
jkanime = true
jkanimeName = jkAnimeTitles[name].search
}
}
if (jkanime === false) {
let options = { scrapy: true }
$ = await homgot(`${SEARCH_URL}${query}`, options);
$('div.Container ul.ListAnimes li article').each((index, element) => {
@ -255,6 +451,24 @@ const searchAnime = async (query) => {
})));
})
} else {
let options = { scrapy: true }
$ = await homgot(`${JKANIME_URL}${jkanimeName}`, options);
$('.portada-box').each(function (index, element) {
const $element = $(element);
const title = $element.find('h2.portada-title a').attr('title');
const id = $element.find('a.let-link').attr('href').split('/')[3];
const poster = $element.find('a').children('img').attr('src');
promises.push(helper().then(async () => ({
id: id || null,
title: title || null,
type: 'Anime',
image: await imageUrlToBase64(poster) || null
})))
});
}
return Promise.all(promises);
@ -433,6 +647,7 @@ const getDirectory = async () => {
};
module.exports = {
jkanimeInfo,
animeflvInfo,
getAnimeCharacters,
getAnimeVideoPromo,
@ -445,5 +660,6 @@ module.exports = {
getThemes,
getAnimes,
getDirectory,
helper
helper,
videoServersJK
}

Loading…
Cancel
Save