From b07d16d33d346a0de53ca262259e862e0b716238 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9luchu?= Date: Tue, 14 Jul 2020 00:22:52 +0200 Subject: [PATCH] v2.6.0 - Obtain More Data --- README.md | 2 +- package-lock.json | 7 +- package.json | 5 +- src/api/api.js | 155 +++++++++++++++++-------- src/api/index.js | 2 +- src/api/urls.js | 2 + src/assets/genres.json | 42 +++++++ src/utils/index.js | 254 ++++++++++++++++++++++++++++++++++++++--- 8 files changed, 399 insertions(+), 70 deletions(-) create mode 100644 src/assets/genres.json diff --git a/README.md b/README.md index 16fde9e..21c0a83 100644 --- a/README.md +++ b/README.md @@ -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 > diff --git a/package-lock.json b/package-lock.json index 95acee4..d274794 100644 --- a/package-lock.json +++ b/package-lock.json @@ -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", diff --git a/package.json b/package.json index 89c660f..ad7965d 100644 --- a/package.json +++ b/package.json @@ -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" } } diff --git a/src/api/api.js b/src/api/api.js index d1d5aa5..8da90b6 100644 --- a/src/api/api.js +++ b/src/api/api.js @@ -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,46 +258,65 @@ const getMoreInfo = async (title) =>{ let seriesTitle let position - 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' } + 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' } ]; - for (let name in titles) { - if (title === titles[name].animeflv || title === titles[name].myanimelist || title === titles[name].alternative) { - seriesTitle = titles[name].animeflv - position = name + 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 (seriesTitle === undefined) { - seriesTitle = 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: '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) { - 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() + await getAllAnimes().then(animes => { - if (position !== undefined) { - seriesTitle = titles[position].myanimelist - } + for (const i in 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() - 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 => ({ title: animeTitle || null, poster: await imageUrlToBase64(extra.animeExtraInfo[0].poster) || null, @@ -315,21 +336,42 @@ const getMoreInfo = async (title) =>{ return characters || null }) }))); - } else { - promises.push(await animeflvInfo(animeId).then(async extra => ({ - title: animeTitle || 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, - }))); - } + } else { + promises.push(await animeflvInfo(animeId).then(async extra => ({ + title: animeTitle || 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, + }))); + } - }catch(err){ - console.log(err) + }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,11 +380,32 @@ const getMoreInfo = async (title) =>{ const getAnimeServers = async (id) => { - let options = { parse: true } - const data = await homgot(`${BASE_ANIMEFLV_JELU}GetAnimeServers/${id}`, options); - let body = data.servers; + const jkAnimeIDs = [ + { id: 'the-god-of-high-school' }, + { 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) + } }; diff --git a/src/api/index.js b/src/api/index.js index e4e7026..391f533 100644 --- a/src/api/index.js +++ b/src/api/index.js @@ -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: [ { diff --git a/src/api/urls.js b/src/api/urls.js index 9a233b9..c5fdfe2 100644 --- a/src/api/urls.js +++ b/src/api/urls.js @@ -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/', diff --git a/src/assets/genres.json b/src/assets/genres.json new file mode 100644 index 0000000..999e5fa --- /dev/null +++ b/src/assets/genres.json @@ -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" } +] diff --git a/src/utils/index.js b/src/utils/index.js index 363e4e2..0831a4f 100644 --- a/src/utils/index.js +++ b/src/utils/index.js @@ -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}] = \'