diff --git a/README.md b/README.md index 57738b5..c22413f 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# **Aruppi API** (v3.3.6) +# **Aruppi API** (v3.3.7) > 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 607830d..b5debba 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "aruppi", - "version": "3.3.6", + "version": "3.3.7", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 69f29d2..7ecea89 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "aruppi", - "version": "3.3.6", + "version": "3.3.7", "description": "Aruppi is a custom API to obtain data from the Japanese culture for the mobile app", "main": "./src/api/api.js", "scripts": { diff --git a/src/api/api.js b/src/api/api.js index 02fbec5..d595865 100644 --- a/src/api/api.js +++ b/src/api/api.js @@ -16,11 +16,11 @@ const { structureThemes, videoServersJK, getThemes, - getMALid + getRelatedAnimes } = require('../utils/index'); const ThemeParser = require('../utils/animetheme'); -const parserThemes = new ThemeParser() +const parserThemes = new ThemeParser(); const { BASE_ANIMEFLV_JELU, BASE_JIKAN, BASE_IVOOX, BASE_QWANT, BASE_YOUTUBE, BASE_THEMEMOE, BASE_ANIMEFLV, BASE_ARUPPI @@ -75,17 +75,19 @@ const getAllAnimes = async () =>{ }; -const getAllDirectory = async (genres) =>{ +const getAllDirectory = async (genres) => { - let data - if (genres === "sfw") { + let data; + + if (genres === 'sfw') { data = JSON.parse(JSON.stringify(require('../assets/directory.json'))).filter(function (item) { return !item.genres.includes("Ecchi") && !item.genres.includes("ecchi"); - }) + }); } else { data = JSON.parse(JSON.stringify(require('../assets/directory.json'))); } + return data.map(doc => ({ id: doc.id, title: doc.title, @@ -101,7 +103,7 @@ const getAllDirectory = async (genres) =>{ }; -const getAnitakume = async () =>{ +const getAnitakume = async () => { const promises = [] @@ -238,45 +240,25 @@ const getMoreInfo = async (title) =>{ try { - const promises = [] - let data = JSON.parse(JSON.stringify(require('../assets/directory.json'))); - const res = data.filter(x => x.title === title || x.mal_title === title)[0]; - - if (!res.jkanime) { - promises.push({ - title: res.title || null, - poster: res.poster || null, - synopsis: res.description || null, - status: res.state || null, - type: res.type || null, - rating: res.score || null, - genres: res.genres || null, - episodes: await animeflvInfo(res.id).then(episodes => episodes || null), - moreInfo: await animeExtraInfo(res.mal_title).then(info => info || null), - promo: await getAnimeVideoPromo(res.mal_title).then(promo => promo || null), - characters: await getAnimeCharacters(res.mal_title).then(characters => characters || null) - }); - } else { - promises.push({ - title: res.title || null, - poster: res.poster || null, - synopsis: res.description || null, - status: res.state || null, - type: res.type || null, - rating: res.score || null, - genres: res.genres || null, - episodes: await jkanimeInfo(res.id).then(episodes => episodes || null), - moreInfo: await animeExtraInfo(res.mal_title).then(info => info || null), - promo: await getAnimeVideoPromo(res.mal_title).then(promo => promo || null), - characters: await getAnimeCharacters(res.mal_title).then(characters => characters || null) - }); + let result = data.filter(anime => anime.title === title)[0]; + + return { + title: result.title || null, + poster: result.poster || null, + synopsis: result.description || null, + status: result.state || null, + type: result.type || null, + rating: result.score || null, + genres: result.genres || null, + moreInfo: await animeExtraInfo(result.mal_title).then(info => info || null), + promo: await getAnimeVideoPromo(result.mal_title).then(promo => promo || null), + characters: await getAnimeCharacters(result.mal_title).then(characters => characters || null), + related: await getRelatedAnimes(result.id) } - return promises; - } catch (e) { - console.log(e) + console.log(e); } }; @@ -285,25 +267,17 @@ const getEpisodes = async (title) =>{ try { - const promises = [] - let data = JSON.parse(JSON.stringify(require('../assets/directory.json'))); - const res = data.filter(x => x.title === title || x.mal_title === title)[0]; + const result = data.filter(x => x.title === title || x.mal_title === title)[0]; - if (!res.jkanime) { - promises.push({ - episodes: await animeflvInfo(res.id).then(episodes => episodes || null), - }); + if (!result.jkanime) { + return await animeflvInfo(result.id).then(episodes => episodes || null); } else { - promises.push({ - episodes: await jkanimeInfo(res.id).then(episodes => episodes || null), - }); + return await jkanimeInfo(result.id).then(episodes => episodes || null); } - return promises; - } catch (e) { - console.log(e) + console.log(e); } }; @@ -311,10 +285,15 @@ const getEpisodes = async (title) =>{ const getAnimeServers = async (id) => { if (isNaN(id.split('/')[0])) { - return await videoServersJK(id) + + return await videoServersJK(id); + } else { + const data = await homgot(`${BASE_ANIMEFLV_JELU}GetAnimeServers/${id}`, { parse: true }); + return await transformUrlServer(data.servers); + } }; @@ -392,7 +371,7 @@ const getOpAndEd = async (title) => await structureThemes(await parserThemes.ser const getThemesYear = async (year) => { - let data = [] + let data = []; if (year === undefined) { return await parserThemes.allYears(); } else { @@ -510,7 +489,7 @@ const getPlatforms = async (id) => { const getProfilePlatform = async (id) => { - let data = await homgot(`${BASE_ARUPPI}res/documents/animelegal/platforms/${id}.json`, { parse: true }) + let data = await homgot(`${BASE_ARUPPI}res/documents/animelegal/platforms/${id}.json`, { parse: true }); let channelId = { id: data[0].youtubeId, part: 'snippet,id', order: 'date', maxResults: '50', prop: 'items' }; let videos = await getYoutubeVideos(channelId) @@ -562,5 +541,6 @@ module.exports = { getDestAnimePlatforms, getPlatforms, getSectionYoutubeVideos, - getProfilePlatform + getProfilePlatform, + getRelatedAnimes }; diff --git a/src/api/apiCall.js b/src/api/apiCall.js index 95fc0cd..47c3935 100644 --- a/src/api/apiCall.js +++ b/src/api/apiCall.js @@ -1,27 +1,30 @@ -const got = require('got'); +const got = require('got'); // This is to make a HTTP request without doing AJAX const cheerio = require('cheerio'); const { CookieJar} = require('tough-cookie'); const cookieJar = new CookieJar(); -let response -let data +let response; +let data; const homgot = async (url, options) => { if (options !== undefined) { + if (options.scrapy) { - response = await got(url, { cookieJar }) - data = await cheerio.load(response.body) + response = await got(url, { cookieJar }); + data = await cheerio.load(response.body); } + if (options.parse) { - data = await got(url, { cookieJar }).json() + data = await got(url, { cookieJar }).json(); } + } else { data = await got.get(url, { cookieJar }); } - return data + return data; } -module.exports = {homgot} +module.exports = { homgot }; diff --git a/src/api/routes/index.js b/src/api/routes/index.js index 7b0170e..9007695 100644 --- a/src/api/routes/index.js +++ b/src/api/routes/index.js @@ -269,14 +269,12 @@ router.get('/moreInfo/:title' , (req, res) =>{ let title = req.params.title; api.getMoreInfo(title) - .then(info =>{ - if (info.length > 0) { - res.status(200).json({ - info - }); - } else ( - res.status(500).json({ message: 'Aruppi lost in the shell'}) - ) + .then(info => { + if (info !== undefined) { + res.status(200).json(info); + } else { + res.status(500).json({ message: 'Aruppi lost in the shell'}); + } }).catch((err) =>{ console.error(err); }); @@ -288,13 +286,15 @@ router.get('/getEpisodes/:title' , (req, res) =>{ let title = req.params.title; api.getEpisodes(title) - .then(episodes =>{ + .then(episodes => { + if (episodes.length > 0) { - res.status(200).json(episodes); - } else ( - res.status(500).json({ message: 'Aruppi lost in the shell'}) - ) + res.status(200).json({episodes}); + } else { + res.status(500).json({ message: 'Aruppi lost in the shell'}); + } }).catch((err) =>{ + console.error(err); }); @@ -310,9 +310,9 @@ router.get('/getAnimeServers/:id([^/]+/[^/]+)' , (req, res) =>{ res.status(200).json({ servers }); - } else ( - res.status(500).json({ message: 'Aruppi lost in the shell'}) - ) + } else { + res.status(500).json({ message: 'Aruppi lost in the shell'}); + } }).catch((err) =>{ console.error(err); }); @@ -433,16 +433,17 @@ router.get('/allThemes', (req, res) =>{ router.get('/themes/:title' , (req, res) =>{ let title = req.params.title; + api.getOpAndEd(title) - .then(themes =>{ - if (themes.length > 0) { + .then(themes => { + if (themes) { res.status(200).json({ themes }); - } else ( - res.status(500).json({ message: 'Aruppi lost in the shell'}) - ) + } else { + res.status(500).json({ message: 'Aruppi lost in the shell'}); + } }).catch((err) =>{ console.error(err); }); diff --git a/src/index.js b/src/index.js index e57e57b..2187fe4 100644 --- a/src/index.js +++ b/src/index.js @@ -13,6 +13,8 @@ function shutdown() { process.exit(); } +// @TESTING + process.on('SIGINT', shutdown); process.on('SIGQUIT', shutdown); process.on('SIGTERM', shutdown); diff --git a/src/utils/animetheme.js b/src/utils/animetheme.js index 8f487a0..3a29ab1 100644 --- a/src/utils/animetheme.js +++ b/src/utils/animetheme.js @@ -19,7 +19,7 @@ class ThemeParser { return await this.parseLinks(); } catch(err) { - throw err; + console.log(err); } } @@ -30,18 +30,18 @@ class ThemeParser { return await this.parseYears(); } catch(err) { - throw err; + console.log(err); } } - async serie(query) { + async serie(title) { try { this.animes = []; this.$ = await redditocall('anime_index'); - return await this.parseSerie(query); + return await this.parseSerie(title); } catch(err) { - throw err; + console.log(err); } } @@ -52,7 +52,7 @@ class ThemeParser { return await this.parseArtists(); } catch(err) { - throw err; + console.log(err); } } @@ -63,7 +63,7 @@ class ThemeParser { return await this.parseArtist(); } catch(err) { - throw err; + console.log(err); } } @@ -74,13 +74,14 @@ class ThemeParser { return await this.parseRandom(query); } catch(err) { - throw err; + console.log(err); } } async year(date) { let animes = []; - this.$ = await redditocall(date) + + this.$ = await redditocall(date); this.$('h3').each((i, el) => { let parsed = this.parseAnime(el); parsed.year = date; @@ -102,13 +103,13 @@ class ThemeParser { let parsed = this.parseAnime(this.$('h3')[rand]); resolve(parsed); - }) + }); } - parseYears(){ + parseYears() { return new Promise(async resolve => { - let promises = [] + let promises = []; let data = this.$('h3 a'); for (let i = 0; i < data.length; i++) { @@ -119,15 +120,15 @@ class ThemeParser { }) if (i === data.length - 1) { - resolve(promises) + resolve(promises); } } - }) + }); } - parseArtists(){ + parseArtists() { return new Promise(async resolve => { let promises = [] @@ -169,22 +170,31 @@ class ThemeParser { }) } - parseSerie(query){ + /* - ParseSerie + Parse the HTML from the redditocall + and search for the h3 tag to be the + same of the title and resolve a object. + */ + parseSerie(title) { return new Promise(async resolve => { let data = this.$('p a'); for (let i = 0; i < data.length; i++) { - let serieElement = data[i].children[0].data - - if (serieElement.split(" (")[0] === query) { + let serieElement = data[i].children[0].data; + + if (serieElement.split(" (")[0] === title) { + let year = this.$('p a')[i].attribs.href.split('/r/AnimeThemes/wiki/')[1].split('#wiki')[0]; this.$ = await redditocall(this.$('p a')[i].attribs.href.split('/r/AnimeThemes/wiki/')[1].split('#wiki')[0]); - + for (let i = 0; i < this.$('h3').length; i++) { - if (this.$('h3')[i].children[0].children[0].data === query) { + + if (this.$('h3')[i].children[0].children[0].data === title) { + let parsed = this.parseAnime(this.$('h3')[i]); + parsed.year = year; resolve(parsed); } } @@ -192,17 +202,18 @@ class ThemeParser { } } - }) + }); } parseLinks() { return new Promise(async resolve => { let years = this.$('h3 a'); - this.$('h3 a')[0].children[0].data + for (let i = 0; i < years.length; i++) { let yearElement = years[i]; + await this.year(this.$(yearElement).attr('href').split('/')[4]) .then(async animes => { this.animes = this.animes.concat(animes); @@ -215,65 +226,80 @@ class ThemeParser { }) } - parseAnime(dat) { - let el = this.$(dat).children('a'); + parseAnime(element) { + let el = this.$(element).children('a'); let title = el.text(); - let malId = el.attr('href').split('/')[4]; - let next = this.$(dat).next(); + let mal_id = el.attr('href').split('/')[4]; + let next = this.$(element).next(); let theme = { - id: malId, + id: mal_id, title - } + }; + + + if (next.prop("tagName") === "TABLE") { - if (next.prop("tagName") === "P") { - theme.themes = this.parseTable(next.next()); - } else if (next.prop("tagName") === "TABLE") { theme.themes = this.parseTable(next); - } + + }else if (next.prop("tagName") === "P") { + + theme.themes = this.parseTable(next.next()); + + } + return theme; } - parseTable(table) { - if (table.prop('tagName') !== "TABLE") { - return this.parseTable(table.next()); + /* - ParseTable + Parse the table tag from the HTML + and returns a object with all the + information. + */ + + parseTable(element) { + + if (element.prop('tagName') !== "TABLE") { + return this.parseTable(element.next()); } let themes = []; - table.children('tbody').children('tr').each(function () { - const $ = cheerio.load(this); - const td = $('td'); // Theme row - let name = replaceAll(td.first().text(), """, "\"") - let linkEl = td.eq(1).children().first(); - let link = linkEl.attr('href'); - let linkDesc = linkEl.text(); - let episodes = td.eq(2).text(); - let notes = td.eq(3).text(); + + element.find('tbody').find('tr').each((i, elem) => { + + let name = replaceAll(elem.children[1].children[0].data, """, "\""); + let link = elem.children[3].children[0].attribs.href; + let linkDesc = elem.children[3].children[0].children[0].data; + let episodes = elem.children[5].children.length > 0 ? elem.children[5].children[0].data : ""; + let notes = elem.children[7].children.length > 0 ? elem.children[7].children[0].data : ""; + + themes.push({ name, link, desc: linkDesc, - type: (name.startsWith('OP') ? 'opening' : 'ending'), + type: name.startsWith('OP') ? 'Opening' : name.startsWith('ED') ? 'Ending' : 'OP/ED', episodes, notes - }) - }) - + }); + }); return themes; + } } async function redditocall(href) { - let resp = await homgot(REDDIT_ANIMETHEMES + href + ".json", { parse: true }) + let resp = await homgot(REDDIT_ANIMETHEMES + href + ".json", { parse: true }); return cheerio.load(getHTML(resp.data.content_html)); } + function getHTML(str) { - let html = replaceAll(str, "<", "<") - html = replaceAll(html, ">", ">") + let html = replaceAll(str, "<", "<"); + html = replaceAll(html, ">", ">"); return html; } @@ -281,4 +307,5 @@ function replaceAll(str, find, replace) { return str.replace(new RegExp(find, 'g'), replace); } + module.exports = ThemeParser; diff --git a/src/utils/index.js b/src/utils/index.js index c61d447..1949653 100644 --- a/src/utils/index.js +++ b/src/utils/index.js @@ -22,91 +22,107 @@ global.btoa = btoa; async function videoServersJK(id) { const $ = await homgot(`${BASE_JKANIME}${id}`, { scrapy: true }); - - const scripts = $('script'); - const episodes = $('div#reproductor-box li'); - const serverNames = []; - let servers = []; - - episodes.each((index, element) => serverNames.push($(element).find('a').text())) - - for (let i = 0; i < scripts.length; i++) { - try { - const contents = $(scripts[i]).html(); - if ((contents || '').includes('var video = [];')) { - Array.from({ length: episodes.length }, (v, k) => { - let index = Number(k + 1); - let videoPageURL = contents.split(`video[${index}] = \'