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 > 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", "name": "aruppi",
"version": "2.4.0", "version": "2.5.0",
"lockfileVersion": 1, "lockfileVersion": 1,
"requires": true, "requires": true,
"dependencies": { "dependencies": {
@ -1162,6 +1162,11 @@
"nan": "^2.13.2" "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": { "normalize-url": {
"version": "4.5.0", "version": "4.5.0",
"resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.0.tgz", "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.0.tgz",

@ -1,6 +1,6 @@
{ {
"name": "aruppi", "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", "description": "Aruppi is a custom API to obtain data from the Japanese culture for the mobile app",
"main": "./src/api/api.js", "main": "./src/api/api.js",
"scripts": { "scripts": {
@ -51,6 +51,7 @@
"helmet": "^3.23.3", "helmet": "^3.23.3",
"hooman": "^1.2.5", "hooman": "^1.2.5",
"rss-to-json": "^1.1.1", "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'); } = require('../api/apiCall');
const { const {
jkanimeInfo,
animeflvInfo, animeflvInfo,
imageUrlToBase64, imageUrlToBase64,
getAnimeCharacters, getAnimeCharacters,
@ -16,7 +17,8 @@ const {
structureThemes, structureThemes,
getAnimes, getAnimes,
getDirectory, getDirectory,
helper helper,
videoServersJK
} = require('../utils/index'); } = require('../utils/index');
const ThemeParser = require('../utils/animetheme'); const ThemeParser = require('../utils/animetheme');
@ -256,46 +258,65 @@ const getMoreInfo = async (title) =>{
let seriesTitle let seriesTitle
let position let position
const titles = [ const jkAnimeTitles = [
{ 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'}, { title: 'The God of High School', id: 'the-god-of-high-school' },
{ animeflv: 'Naruto Shippuden', myanimelist: 'Naruto: Shippuuden' }, { title: 'Kami no Tou', id: 'kami-no-tou' },
{ animeflv: 'Rock Lee no Seishun Full-Power Ninden', myanimelist: 'Naruto SD: Rock Lee no Seishun Full-Power Ninden' } { title: 'BNA', id: 'bna' }
]; ];
for (let name in titles) { let jkanime = false
if (title === titles[name].animeflv || title === titles[name].myanimelist || title === titles[name].alternative) { let jkanimeID
seriesTitle = titles[name].animeflv let jkanimeName
position = name for (let name in jkAnimeTitles) {
if (title === jkAnimeTitles[name].title) {
jkanime = true
jkanimeID = jkAnimeTitles[name].id
jkanimeName = jkAnimeTitles[name].title
} }
} }
if (seriesTitle === undefined) { if (jkanime === false) {
seriesTitle = title 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: 'BAKI: dai reitaisai-hen', myanimelist: 'Baki 2nd Season' }
];
for (let name in titles) {
if (title === titles[name].animeflv || title === titles[name].myanimelist || title === titles[name].alternative) {
seriesTitle = titles[name].animeflv
position = name
}
}
await getAllAnimes().then(animes => { if (seriesTitle === undefined) {
seriesTitle = title
}
for (const i in animes) { await getAllAnimes().then(animes => {
if (animes[i].title.split('\t')[0] === seriesTitle.split('\t')[0] || animes[i].title === `${seriesTitle} (TV)`) {
if (animes[i].title.includes('(TV)', 0)) { animeTitle = animes[i].title.split('\t')[0].replace(' (TV)', '') }
else { animeTitle = animes[i].title.split('\t')[0] }
animeId = animes[i].id
animeIndex = animes[i].index
animeType = animes[i].type.toLowerCase()
if (position !== undefined) { for (const i in animes) {
seriesTitle = titles[position].myanimelist if (animes[i].title.split('\t')[0] === seriesTitle.split('\t')[0] || animes[i].title === `${seriesTitle} (TV)`) {
} if (animes[i].title.includes('(TV)', 0)) { animeTitle = animes[i].title.split('\t')[0].replace(' (TV)', '') }
else { animeTitle = animes[i].title.split('\t')[0] }
animeId = animes[i].id
animeIndex = animes[i].index
animeType = animes[i].type.toLowerCase()
break; if (position !== undefined) {
seriesTitle = titles[position].myanimelist
}
break;
}
} }
} });
});
try{ try{
if (animeType === 'tv') { if (animeType === 'tv') {
promises.push(await animeflvInfo(animeId, animeIndex).then(async extra => ({ promises.push(await animeflvInfo(animeId, animeIndex).then(async extra => ({
title: animeTitle || null, title: animeTitle || null,
poster: await imageUrlToBase64(extra.animeExtraInfo[0].poster) || null, poster: await imageUrlToBase64(extra.animeExtraInfo[0].poster) || null,
@ -315,21 +336,42 @@ const getMoreInfo = async (title) =>{
return characters || null return characters || null
}) })
}))); })));
} else { } else {
promises.push(await animeflvInfo(animeId).then(async extra => ({ promises.push(await animeflvInfo(animeId).then(async extra => ({
title: animeTitle || null, title: animeTitle || null,
poster: await imageUrlToBase64(extra.animeExtraInfo[0].poster) || null, poster: await imageUrlToBase64(extra.animeExtraInfo[0].poster) || null,
synopsis: extra.animeExtraInfo[0].synopsis || null, synopsis: extra.animeExtraInfo[0].synopsis || null,
status: extra.animeExtraInfo[0].debut || null, status: extra.animeExtraInfo[0].debut || null,
type: extra.animeExtraInfo[0].type || null, type: extra.animeExtraInfo[0].type || null,
rating: extra.animeExtraInfo[0].rating || null, rating: extra.animeExtraInfo[0].rating || null,
genres: extra.genres || null, genres: extra.genres || null,
episodes: extra.listByEps || null, episodes: extra.listByEps || null,
}))); })));
} }
}catch(err){ }catch(err){
console.log(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; return promises;
@ -338,11 +380,32 @@ const getMoreInfo = async (title) =>{
const getAnimeServers = async (id) => { const getAnimeServers = async (id) => {
let options = { parse: true } const jkAnimeIDs = [
const data = await homgot(`${BASE_ANIMEFLV_JELU}GetAnimeServers/${id}`, options); { id: 'the-god-of-high-school' },
let body = data.servers; { id: 'kami-no-tou' },
{ id: 'bna' }
];
return await transformUrlServer(body); 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)
}
}; };

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

@ -1,6 +1,7 @@
module.exports = { module.exports = {
BASE_ARUPPI: 'https://aruppi.jeluchu.xyz/', BASE_ARUPPI: 'https://aruppi.jeluchu.xyz/',
BASE_ANIMEFLV: 'https://animeflv.net/', BASE_ANIMEFLV: 'https://animeflv.net/',
BASE_JKANIME: 'https://jkanime.net/',
BASE_ANIMEFLV_JELU: 'https://aruppi.jeluchu.xyz/apis/animeflv/v1/', BASE_ANIMEFLV_JELU: 'https://aruppi.jeluchu.xyz/apis/animeflv/v1/',
BASE_YOUTUBE: 'https://aruppi.jeluchu.xyz/apis/youtube/v3/search?channelId=', BASE_YOUTUBE: 'https://aruppi.jeluchu.xyz/apis/youtube/v3/search?channelId=',
BASE_JIKAN: 'https://aruppi.jeluchu.xyz/apis/jikan/v3/', 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_RAMENPARADOS: 'https://ramenparados.com/category/noticias/anime/feed/',
BASE_CRUNCHYROLL: 'https://www.crunchyroll.com/newsrss?lang=esES', BASE_CRUNCHYROLL: 'https://www.crunchyroll.com/newsrss?lang=esES',
SEARCH_URL: 'https://animeflv.net/browse?q=', SEARCH_URL: 'https://animeflv.net/browse?q=',
JKANIME_URL: 'https://jkanime.net/buscar/',
GENRES_URL: 'https://animeflv.net/browse?', GENRES_URL: 'https://animeflv.net/browse?',
SEARCH_DIRECTORY: 'https://animeflv.net/browse?order=title&page=', SEARCH_DIRECTORY: 'https://animeflv.net/browse?order=title&page=',
BASE_EPISODE_IMG_URL: 'https://cdn.animeflv.net/screenshots/', 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 { 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'); } = require('../api/urls');
const { const {
homgot homgot
} = require('../api/apiCall'); } = 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) => { const animeflvInfo = async (id, index) => {
let poster = "" let poster = ""
@ -205,6 +379,13 @@ const animeExtraInfo = async (title) => {
'default': 'Sin emisión' 'default': 'Sin emisión'
}; };
let broadcast
if (doc.broadcast === null) {
broadcast = null
} else {
broadcast = airDay[doc.broadcast.split('at')[0].replace(" ", "").toLowerCase()]
}
promises.push({ promises.push({
titleJapanese: doc.title_japanese, titleJapanese: doc.title_japanese,
source: doc.source, source: doc.source,
@ -215,7 +396,7 @@ const animeExtraInfo = async (title) => {
}, },
duration: doc.duration.split('per')[0], duration: doc.duration.split('per')[0],
rank: doc.rank, rank: doc.rank,
broadcast: airDay[doc.broadcast.split('at')[0].replace(" ", "").toLowerCase()], broadcast: broadcast,
producers: doc.producers.map(x => x.name) || null, producers: doc.producers.map(x => x.name) || null,
licensors: doc.licensors.map(x => x.name) || null, licensors: doc.licensors.map(x => x.name) || null,
studios: doc.studios.map(x => x.name) || null, studios: doc.studios.map(x => x.name) || null,
@ -238,23 +419,56 @@ const searchAnime = async (query) => {
let $ let $
let promises = [] let promises = []
let options = { scrapy: true } const jkAnimeTitles = [
$ = await homgot(`${SEARCH_URL}${query}`, options); { title: 'BNA', search: 'BNA'},
$('div.Container ul.ListAnimes li article').each((index, element) => { { title: 'The God of High School', search: 'The god' }
const $element = $(element); ];
const id = $element.find('div.Description a.Button').attr('href').slice(1);
const title = $element.find('a h3').text(); let jkanime = false
let poster = $element.find('a div.Image figure img').attr('src') || $element.find('a div.Image figure img').attr('data-cfsrc'); let jkanimeName
const type = $element.find('div.Description p span.Type').text(); for (let name in jkAnimeTitles) {
if (query === jkAnimeTitles[name].title) {
promises.push(helper().then(async () => ({ jkanime = true
id: id || null, jkanimeName = jkAnimeTitles[name].search
title: title || null, }
type: type || null, }
image: await imageUrlToBase64(poster) || null
})));
}) if (jkanime === false) {
let options = { scrapy: true }
$ = await homgot(`${SEARCH_URL}${query}`, options);
$('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(helper().then(async () => ({
id: id || null,
title: title || null,
type: type || null,
image: await imageUrlToBase64(poster) || null
})));
})
} 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); return Promise.all(promises);
@ -433,6 +647,7 @@ const getDirectory = async () => {
}; };
module.exports = { module.exports = {
jkanimeInfo,
animeflvInfo, animeflvInfo,
getAnimeCharacters, getAnimeCharacters,
getAnimeVideoPromo, getAnimeVideoPromo,
@ -445,5 +660,6 @@ module.exports = {
getThemes, getThemes,
getAnimes, getAnimes,
getDirectory, getDirectory,
helper helper,
videoServersJK
} }

Loading…
Cancel
Save