mirror of https://github.com/aruppi/aruppi-api
v3.0.0 - Full Directory - Supports v2.6.8
This commit is contained in:
parent
cfa6b05917
commit
1e357ad206
|
@ -1,4 +1,4 @@
|
|||
# **Aruppi API** (v2.7.1)
|
||||
# **Aruppi API** (v3.0.0)
|
||||
|
||||
> This API has everything about Japan, from anime, music, radio, images, videos ... to japanese culture
|
||||
>
|
||||
|
@ -69,6 +69,12 @@ But if you need to see the code or the operation of the old version you can do i
|
|||
- [Aruppi API GitHub (v1) [Deprecated]](https://github.com/aruppi/aruppi-api-v1)
|
||||
- [Aruppi API Custom Link(v1) [Deprecated]](https://aruppi.herokuapp.com/api/Aruppi/)
|
||||
|
||||
## Countdown to deprecation of v2 API
|
||||
|
||||
Aruppi has grown since it was launched and we need to continue improving the application along with the services to be able to give new features.
|
||||
|
||||
At this time version 2.6.8 will remain functional until Aruppi App users fully migrate to version 1.5.0 of the app
|
||||
|
||||
## **:handshake: Contributing**
|
||||
|
||||
- Fork it!
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "aruppi",
|
||||
"version": "2.7.1",
|
||||
"version": "3.0.0",
|
||||
"description": "Aruppi is a custom API to obtain data from the Japanese culture for the mobile app",
|
||||
"main": "./src/api/api.js",
|
||||
"scripts": {
|
||||
|
|
|
@ -13,32 +13,32 @@ router.get('/', (req, res) => {
|
|||
credits: 'The bitch loves APIs that offers data to Aruppi App',
|
||||
entries: [
|
||||
{
|
||||
'Schedule': '/api/v2/schedule/:day',
|
||||
'Top': '/api/v2/top/:type/:subtype/:page',
|
||||
'AllAnimes': '/api/v2/allAnimes',
|
||||
'Anitakume': '/api/v2/anitakume',
|
||||
'News': '/api/v2/news',
|
||||
'Season': '/api/v2/season/:year/:type',
|
||||
'All Seasons': '/api/v2/allSeasons',
|
||||
'All Directory': '/api/v2/allDirectory',
|
||||
'Genres': '/api/v2/getByGenres/:genre/:order/:page?',
|
||||
'Futures Seasons': '/api/v2/laterSeasons',
|
||||
'LastEpisodes': '/api/v2/lastEpisodes',
|
||||
'Movies': '/api/v2/movies/:type/:page',
|
||||
'Ovas': '/api/v2/ovas/:type/:page',
|
||||
'Specials': '/api/v2/specials/:type/:page',
|
||||
'Tv': '/api/v2/tv/:type/:page',
|
||||
'MoreInfo': '/api/v2/moreInfo/:title',
|
||||
'GetAnimeServers': '/api/v2/getAnimeServers/:id',
|
||||
'Search': '/api/v2/search/:title',
|
||||
'Images': '/api/v2/images/:query',
|
||||
'Videos': '/api/v2/videos/:channelId',
|
||||
'Radios': '/api/v2/radio',
|
||||
'All Themes': '/api/v2/allThemes',
|
||||
'Themes': '/api/v2/themes/:title',
|
||||
'Year Themes': '/api/v2/themesYear/:year?',
|
||||
'Random Theme': '/api/v2/randomTheme',
|
||||
'Artists Theme': '/api/v2/artists/:id?'
|
||||
'Schedule': '/api/v3/schedule/:day',
|
||||
'Top': '/api/v3/top/:type/:subtype/:page',
|
||||
'AllAnimes': '/api/v3/allAnimes',
|
||||
'Anitakume': '/api/v3/anitakume',
|
||||
'News': '/api/v3/news',
|
||||
'Season': '/api/v3/season/:year/:type',
|
||||
'All Seasons': '/api/v3/allSeasons',
|
||||
'All Directory': '/api/v3/allDirectory',
|
||||
'Genres': '/api/v3/getByGenres/:genre/:order/:page?',
|
||||
'Futures Seasons': '/api/v3/laterSeasons',
|
||||
'LastEpisodes': '/api/v3/lastEpisodes',
|
||||
'Movies': '/api/v3/movies/:type/:page',
|
||||
'Ovas': '/api/v3/ovas/:type/:page',
|
||||
'Specials': '/api/v3/specials/:type/:page',
|
||||
'Tv': '/api/v3/tv/:type/:page',
|
||||
'MoreInfo': '/api/v3/moreInfo/:title',
|
||||
'GetAnimeServers': '/api/v3/getAnimeServers/:id',
|
||||
'Search': '/api/v3/search/:title',
|
||||
'Images': '/api/v3/images/:query',
|
||||
'Videos': '/api/v3/videos/:channelId',
|
||||
'Radios': '/api/v3/radio',
|
||||
'All Themes': '/api/v3/allThemes',
|
||||
'Themes': '/api/v3/themes/:title',
|
||||
'Year Themes': '/api/v3/themesYear/:year?',
|
||||
'Random Theme': '/api/v3/randomTheme',
|
||||
'Artists Theme': '/api/v3/artists/:id?'
|
||||
}
|
||||
]
|
||||
});
|
||||
|
|
|
@ -7,6 +7,8 @@ const version = require('./../package.json').version;
|
|||
const middlewares = require('./middlewares/index').middleware;
|
||||
const api = require('./api');
|
||||
|
||||
const api_legacy = require('./v2/api');
|
||||
|
||||
const app = express();
|
||||
|
||||
app.use(helmet());
|
||||
|
@ -37,7 +39,8 @@ app.get('/api/v1', (req, res) => {
|
|||
});
|
||||
});
|
||||
|
||||
app.use('/api/v2', api);
|
||||
app.use('/api/v2', api_legacy);
|
||||
app.use('/api/v3', api);
|
||||
|
||||
app.use(middlewares);
|
||||
|
||||
|
|
|
@ -429,7 +429,6 @@ const getThemes = async (themes) => {
|
|||
name: doc.themeName,
|
||||
type: doc.themeType,
|
||||
video: doc.mirror.mirrorURL
|
||||
`${BASE_ANIMEFLV}anime/${id}`
|
||||
}));
|
||||
|
||||
};
|
||||
|
|
|
@ -0,0 +1,606 @@
|
|||
const rss = require('rss-to-json');
|
||||
|
||||
const {
|
||||
homgot
|
||||
} = require('./apiCall');
|
||||
|
||||
const {
|
||||
jkanimeInfo,
|
||||
animeflvGenres,
|
||||
animeflvInfo,
|
||||
imageUrlToBase64,
|
||||
getAnimeCharacters,
|
||||
getAnimeVideoPromo,
|
||||
animeExtraInfo,
|
||||
searchAnime,
|
||||
transformUrlServer,
|
||||
obtainPreviewNews,
|
||||
structureThemes,
|
||||
getAnimes,
|
||||
getDirectory,
|
||||
helper,
|
||||
videoServersJK,
|
||||
getThemes
|
||||
} = require('../utils');
|
||||
|
||||
const ThemeParser = require('../utils/animetheme');
|
||||
const parserThemes = new ThemeParser()
|
||||
|
||||
const {
|
||||
BASE_ANIMEFLV_JELU, BASE_JIKAN, BASE_IVOOX, BASE_QWANT, BASE_YOUTUBE, GENRES_URL, BASE_THEMEMOE
|
||||
} = require('./urls');
|
||||
|
||||
const schedule = async (day) =>{
|
||||
|
||||
let options = { parse: true }
|
||||
const data = await homgot(`${BASE_JIKAN}schedule/${day.current}`, options);
|
||||
const body = data[day.current];
|
||||
const promises = []
|
||||
|
||||
body.map(doc =>{
|
||||
|
||||
promises.push({
|
||||
title: doc.title,
|
||||
malid: doc.mal_id,
|
||||
image: doc.image_url
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
return promises;
|
||||
|
||||
};
|
||||
|
||||
const top = async (type, subtype, page) =>{
|
||||
let options = { parse: true }
|
||||
const data = await homgot(`${BASE_JIKAN}top/${type}/${page}/${subtype}`, options);
|
||||
return data.top;
|
||||
};
|
||||
|
||||
const getAllAnimes = async () =>{
|
||||
|
||||
let data = await getAnimes()
|
||||
|
||||
return data.map(item => ({
|
||||
index: item[0],
|
||||
animeId: item[3],
|
||||
title: item[1],
|
||||
id: item[2],
|
||||
type: item[4]
|
||||
}));
|
||||
|
||||
};
|
||||
|
||||
const getAllDirectory = async () =>{ return await getDirectory(); };
|
||||
|
||||
const getAnitakume = async () =>{
|
||||
|
||||
const promises = []
|
||||
|
||||
await rss.load(BASE_IVOOX).then(rss => {
|
||||
|
||||
const body = JSON.parse(JSON.stringify(rss, null, 3)).items
|
||||
body.map(doc =>{
|
||||
|
||||
let time = new Date(doc.created)
|
||||
const monthNames = ["Enero", "Febrero", "Marzo", "Abril", "Mayo", "Junio", "Julio", "Agosto", "Septiembre", "Octubre", "Noviembre", "Diciembre"];
|
||||
|
||||
let day = time.getDate()
|
||||
let month = monthNames[time.getMonth()]
|
||||
let year = time.getFullYear()
|
||||
let date
|
||||
|
||||
if(month < 10){
|
||||
date = `${day} de 0${month} de ${year}`
|
||||
}else{
|
||||
date = `${day} de ${month} de ${year}`
|
||||
}
|
||||
|
||||
promises.push({
|
||||
title: doc.title,
|
||||
duration: doc.itunes_duration,
|
||||
created: date,
|
||||
mp3: doc.enclosures.map(x => x.url)
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
return promises;
|
||||
|
||||
};
|
||||
|
||||
const getNews = async (pageRss) =>{
|
||||
|
||||
const promises = []
|
||||
|
||||
for(let i = 0; i <= pageRss.length -1; i++) {
|
||||
|
||||
await rss.load(pageRss[i].url).then(rss => {
|
||||
|
||||
const body = JSON.parse(JSON.stringify(rss, null, 3)).items
|
||||
body.map(doc => {
|
||||
|
||||
promises.push({
|
||||
title: doc.title,
|
||||
url: doc.link,
|
||||
author: pageRss[i].author,
|
||||
thumbnail: obtainPreviewNews(doc[pageRss[i].content]),
|
||||
content: doc[pageRss[i].content]
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
return promises;
|
||||
|
||||
};
|
||||
|
||||
const season = async (year, type) =>{
|
||||
|
||||
let options = { parse: true }
|
||||
const data = await homgot(`${BASE_JIKAN}season/${year}/${type}`, options);
|
||||
let body = data.anime;
|
||||
const promises = []
|
||||
|
||||
body.map(doc =>{
|
||||
|
||||
promises.push({
|
||||
title: doc.title,
|
||||
malid: doc.mal_id,
|
||||
image: doc.image_url,
|
||||
genres: doc.genres.map(x => x.name)
|
||||
});
|
||||
});
|
||||
|
||||
return promises;
|
||||
|
||||
};
|
||||
|
||||
const allSeasons = async () =>{
|
||||
|
||||
let options = { parse: true }
|
||||
const data = await homgot(`${BASE_JIKAN}season/archive`, options);
|
||||
let body = data.archive;
|
||||
const promises = []
|
||||
|
||||
body.map(doc =>{
|
||||
|
||||
promises.push({
|
||||
year: doc.year,
|
||||
seasons: doc.seasons,
|
||||
});
|
||||
});
|
||||
|
||||
return promises;
|
||||
|
||||
};
|
||||
|
||||
const laterSeasons = async () =>{
|
||||
|
||||
let options = { parse: true }
|
||||
const data = await homgot(`${BASE_JIKAN}season/later`, options);
|
||||
let body = data.anime;
|
||||
const promises = []
|
||||
|
||||
body.map(doc =>{
|
||||
|
||||
promises.push({
|
||||
malid: doc.mal_id,
|
||||
title: doc.title,
|
||||
image: doc.image_url
|
||||
});
|
||||
});
|
||||
|
||||
return promises;
|
||||
|
||||
};
|
||||
|
||||
const getLastEpisodes = async () =>{
|
||||
|
||||
let options = { parse: true }
|
||||
const data = await homgot(`${BASE_ANIMEFLV_JELU}LatestEpisodesAdded`, options);
|
||||
let body = data.episodes;
|
||||
const promises = []
|
||||
|
||||
body.map(doc => {
|
||||
|
||||
promises.push(helper().then(async () => ({
|
||||
id: doc.id,
|
||||
title: doc.title,
|
||||
image: doc.poster,
|
||||
episode: doc.episode,
|
||||
servers: await transformUrlServer(JSON.parse(JSON.stringify(doc.servers)))
|
||||
})));
|
||||
|
||||
});
|
||||
|
||||
return Promise.all(promises);
|
||||
|
||||
};
|
||||
|
||||
const getSpecials = async (type, subType, page) =>{
|
||||
|
||||
let options = { parse: true }
|
||||
const data = await homgot(`${BASE_ANIMEFLV_JELU}${type.url}/${subType}/${page}`, options);
|
||||
let body = data[type.prop];
|
||||
const promises = []
|
||||
|
||||
body.map(doc =>{
|
||||
|
||||
promises.push({
|
||||
id: doc.id,
|
||||
title: doc.title,
|
||||
type: doc.type,
|
||||
banner: doc.banner,
|
||||
image: doc.poster,
|
||||
synopsis: doc.synopsis,
|
||||
status: doc.debut,
|
||||
rate: doc.rating,
|
||||
genres: doc.genres.map(x => x),
|
||||
episodes: doc.episodes.map(x => x)
|
||||
});
|
||||
});
|
||||
|
||||
return promises;
|
||||
|
||||
};
|
||||
|
||||
const getMoreInfo = async (title) =>{
|
||||
|
||||
const promises = []
|
||||
let animeTitle = ''
|
||||
let animeId = ''
|
||||
let animeType = ''
|
||||
let animeIndex = ''
|
||||
|
||||
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' },
|
||||
{ title: 'Ansatsu Kyoushitsu (TV)', id: 'ansatsu-kyoushitsu-tv' },
|
||||
{ title: 'Ansatsu Kyoushitsu (TV) 2nd Season', id: 'ansatsu-kyoushitsu-tv-2nd-season' }
|
||||
];
|
||||
|
||||
const jkMyAnimetitles = [
|
||||
{ jkanime: 'Ansatsu Kyoushitsu (TV)', myanimelist: 'Ansatsu Kyoushitsu'},
|
||||
{ jkanime: 'Ansatsu Kyoushitsu (TV) 2nd Season', myanimelist: 'Ansatsu Kyoushitsu 2nd Season' }
|
||||
];
|
||||
|
||||
let jkanime = false
|
||||
let jkanimeID
|
||||
let jkanimeName
|
||||
for (let name in jkAnimeTitles) {
|
||||
if (title === jkAnimeTitles[name].title) {
|
||||
jkanime = true
|
||||
jkanimeID = jkAnimeTitles[name].id
|
||||
|
||||
for (let name in jkMyAnimetitles) {
|
||||
if (title === jkMyAnimetitles[name].jkanime || title === jkMyAnimetitles[name].myanimelist) {
|
||||
jkanimeName = jkMyAnimetitles[name].myanimelist
|
||||
position = name
|
||||
}
|
||||
}
|
||||
|
||||
if (jkanimeName === undefined) {
|
||||
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: 'BAKI: dai reitaisai-hen', myanimelist: 'Baki 2nd Season' },
|
||||
{ animeflv: 'Hitoribocchi no ○○ Seikatsu', myanimelist: 'Hitoribocchi no Marumaru Seikatsu' },
|
||||
{ animeflv: 'Nekopara (TV)', myanimelist: 'Nekopara' },
|
||||
{ animeflv: 'Black Clover (TV)', myanimelist: 'Black Clover' }
|
||||
];
|
||||
|
||||
for (let name in titles) {
|
||||
if (title === titles[name].animeflv || title === titles[name].myanimelist || title === titles[name].alternative) {
|
||||
seriesTitle = titles[name].animeflv
|
||||
position = name
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (seriesTitle === undefined) {
|
||||
seriesTitle = title
|
||||
}
|
||||
|
||||
await getAllAnimes().then(animes => {
|
||||
|
||||
for (const i in animes) {
|
||||
if (animes[i].title.split('\t')[0] === seriesTitle.split('\t')[0] ||
|
||||
animes[i].title === `${seriesTitle} (TV)` ||
|
||||
animes[i].title.includes(seriesTitle.split('○')[0])
|
||||
) {
|
||||
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) {
|
||||
seriesTitle = titles[position].myanimelist
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
try{
|
||||
|
||||
if (animeType === 'tv') {
|
||||
promises.push(await animeflvInfo(animeId, animeIndex).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,
|
||||
moreInfo: await animeExtraInfo(seriesTitle).then(info =>{
|
||||
return info || null
|
||||
}),
|
||||
promo: await getAnimeVideoPromo(seriesTitle).then(promo =>{
|
||||
return promo || null
|
||||
}),
|
||||
characters: await getAnimeCharacters(seriesTitle).then(characters =>{
|
||||
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,
|
||||
})));
|
||||
}
|
||||
|
||||
}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;
|
||||
|
||||
};
|
||||
|
||||
const getAnimeServers = async (id) => {
|
||||
|
||||
const jkAnimeIDs = [
|
||||
{ id: 'the-god-of-high-school' },
|
||||
{ id: 'kami-no-tou' },
|
||||
{ id: 'bna' },
|
||||
{ id: 'ansatsu-kyoushitsu-tv' },
|
||||
{ id: 'ansatsu-kyoushitsu-tv-2nd-season' }
|
||||
];
|
||||
|
||||
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); };
|
||||
|
||||
const getImages = async (query) => {
|
||||
|
||||
let options = { parse: true }
|
||||
const data = await homgot(`${BASE_QWANT}count=${query.count}&q=${query.title}&t=${query.type}&safesearch=${query.safesearch}&locale=${query.country}&uiv=4`, options);
|
||||
const body = data.data.result.items;
|
||||
const promises = []
|
||||
|
||||
body.map(doc =>{
|
||||
|
||||
promises.push({
|
||||
type: doc.thumb_type,
|
||||
thumbnail: `https:${doc.thumbnail}`,
|
||||
fullsize: `https:${doc.media_fullsize}`
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
return promises;
|
||||
|
||||
};
|
||||
|
||||
const getYoutubeVideos = async (channelId) => {
|
||||
|
||||
let options = { parse: true }
|
||||
const data = await homgot(`${BASE_YOUTUBE}${channelId.id}&part=${channelId.part}&order=${channelId.order}&maxResults=${channelId.maxResults}`, options);
|
||||
const body = data[channelId.prop];
|
||||
const promises = []
|
||||
|
||||
body.map(doc =>{
|
||||
|
||||
promises.push({
|
||||
title: doc.snippet.title,
|
||||
videoId: doc.id.videoId,
|
||||
thumbDefault: doc.snippet.thumbnails.default.url,
|
||||
thumbMedium: doc.snippet.thumbnails.medium.url,
|
||||
thumbHigh: doc.snippet.thumbnails.high.url
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
return promises;
|
||||
|
||||
};
|
||||
|
||||
const getRadioStations = async () => {
|
||||
return require('../assets/radiostations.json');
|
||||
}
|
||||
|
||||
const getOpAndEd = async (title) => {
|
||||
let data = await parserThemes.serie(title)
|
||||
return await structureThemes(data, true)
|
||||
};
|
||||
|
||||
const getThemesYear = async (year) => {
|
||||
let data = []
|
||||
|
||||
if (year === undefined) {
|
||||
return await parserThemes.allYears();
|
||||
} else {
|
||||
data = await parserThemes.year(year)
|
||||
return await structureThemes(data, false)
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
const getRandomTheme = async () => {
|
||||
|
||||
let promise = []
|
||||
let options = { parse: true }
|
||||
const data = await homgot(`${BASE_THEMEMOE}roulette`, options);
|
||||
let themes = await getThemes(data.themes)
|
||||
|
||||
promise.push({
|
||||
name: data.name,
|
||||
title: themes[0].name,
|
||||
link: themes[0].video
|
||||
})
|
||||
|
||||
return promise;
|
||||
};
|
||||
|
||||
const getArtist = async (id) => {
|
||||
|
||||
let data
|
||||
|
||||
if (id === undefined) {
|
||||
return await parserThemes.artists();
|
||||
} else {
|
||||
data = await parserThemes.artist(id)
|
||||
return await structureThemes(data, false)
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
const getAnimeGenres = async(genre, order, page) => {
|
||||
|
||||
let $
|
||||
let promises = []
|
||||
let options = { scrapy: true }
|
||||
|
||||
if (page !== undefined) {
|
||||
$ = await homgot(`${GENRES_URL}genre%5B%5D=${genre}&order=${order}&page=${page}`,options)
|
||||
} else {
|
||||
$ = await homgot(`${GENRES_URL}genre%5B%5D=${genre}&order=${order}`,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();
|
||||
const poster = $element.find('a div.Image figure img').attr('src');
|
||||
const banner = poster.replace('covers' , 'banners').trim();
|
||||
const type = $element.find('div.Description p span.Type').text();
|
||||
const synopsis = $element.find('div.Description p').eq(1).text().trim();
|
||||
const rating = $element.find('div.Description p span.Vts').text();
|
||||
|
||||
promises.push(animeflvGenres(id).then(async genres => ({
|
||||
id: id || null,
|
||||
title: title || null,
|
||||
poster: await imageUrlToBase64(poster) || null,
|
||||
banner: banner || null,
|
||||
synopsis: synopsis || null,
|
||||
type: type || null,
|
||||
rating: rating || null,
|
||||
genres: genres || null
|
||||
})))
|
||||
|
||||
})
|
||||
|
||||
return Promise.all(promises);
|
||||
|
||||
};
|
||||
|
||||
const getAllThemes = async () => {
|
||||
let data = await parserThemes.all()
|
||||
return await structureThemes(data, false)
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
schedule,
|
||||
top,
|
||||
getAllAnimes,
|
||||
getAllDirectory,
|
||||
getAnitakume,
|
||||
getNews,
|
||||
season,
|
||||
allSeasons,
|
||||
laterSeasons,
|
||||
getLastEpisodes,
|
||||
getSpecials,
|
||||
getMoreInfo,
|
||||
getAnimeServers,
|
||||
search,
|
||||
getImages,
|
||||
getYoutubeVideos,
|
||||
getRadioStations,
|
||||
getOpAndEd,
|
||||
getThemesYear,
|
||||
getRandomTheme,
|
||||
getArtist,
|
||||
getAnimeGenres,
|
||||
getAllThemes
|
||||
};
|
|
@ -0,0 +1,30 @@
|
|||
const hooman = require('hooman');
|
||||
const { CookieJar } = require('tough-cookie');
|
||||
const cookieJar = new CookieJar();
|
||||
const cheerio = require('cheerio');
|
||||
|
||||
let response
|
||||
let data
|
||||
|
||||
const homgot = async (url, options) => {
|
||||
|
||||
response = await hooman.get(url, cookieJar);
|
||||
|
||||
if (options !== undefined) {
|
||||
if (options.scrapy) {
|
||||
data = await cheerio.load(response.body)
|
||||
}
|
||||
if (options.parse) {
|
||||
data = JSON.parse(response.body)
|
||||
}
|
||||
} else {
|
||||
data = response
|
||||
}
|
||||
|
||||
return data
|
||||
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
homgot
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
const express = require('express');
|
||||
const routes = require('./routes/index');
|
||||
|
||||
const router = express.Router();
|
||||
|
||||
router.get('/', (req, res) => {
|
||||
res.set('Cache-Control', 'no-store');
|
||||
res.json({
|
||||
message: 'Aruppi API - 🎏',
|
||||
author: 'Jéluchu',
|
||||
version: '2.6.8',
|
||||
credits: 'The bitch loves APIs that offers data to Aruppi App',
|
||||
deprecated: 'This version will be available until users migrate to Aruppi App v1.5.0',
|
||||
entries: [
|
||||
{
|
||||
'Schedule': '/api/v2/schedule/:day',
|
||||
'Top': '/api/v2/top/:type/:subtype/:page',
|
||||
'AllAnimes': '/api/v2/allAnimes',
|
||||
'Anitakume': '/api/v2/anitakume',
|
||||
'News': '/api/v2/news',
|
||||
'Season': '/api/v2/season/:year/:type',
|
||||
'All Seasons': '/api/v2/allSeasons',
|
||||
'All Directory': '/api/v2/allDirectory',
|
||||
'Genres': '/api/v2/getByGenres/:genre/:order/:page?',
|
||||
'Futures Seasons': '/api/v2/laterSeasons',
|
||||
'LastEpisodes': '/api/v2/lastEpisodes',
|
||||
'Movies': '/api/v2/movies/:type/:page',
|
||||
'Ovas': '/api/v2/ovas/:type/:page',
|
||||
'Specials': '/api/v2/specials/:type/:page',
|
||||
'Tv': '/api/v2/tv/:type/:page',
|
||||
'MoreInfo': '/api/v2/moreInfo/:title',
|
||||
'GetAnimeServers': '/api/v2/getAnimeServers/:id',
|
||||
'Search': '/api/v2/search/:title',
|
||||
'Images': '/api/v2/images/:query',
|
||||
'Videos': '/api/v2/videos/:channelId',
|
||||
'Radios': '/api/v2/radio',
|
||||
'All Themes': '/api/v2/allThemes',
|
||||
'Themes': '/api/v2/themes/:title',
|
||||
'Year Themes': '/api/v2/themesYear/:year?',
|
||||
'Random Theme': '/api/v2/randomTheme',
|
||||
'Artists Theme': '/api/v2/artists/:id?'
|
||||
}
|
||||
]
|
||||
});
|
||||
});
|
||||
|
||||
router.use('/', routes);
|
||||
|
||||
module.exports = router;
|
|
@ -0,0 +1,501 @@
|
|||
const express = require('express');
|
||||
const router = express.Router();
|
||||
const api = require('../api');
|
||||
|
||||
const { BASE_KUDASAI, BASE_PALOMITRON, BASE_RAMENPARADOS, BASE_CRUNCHYROLL } = require('../urls');
|
||||
|
||||
router.get('/schedule/:day' , (req, res) =>{
|
||||
|
||||
let day = {current: req.params.day}
|
||||
|
||||
api.schedule(day)
|
||||
.then(day =>{
|
||||
if (day.length > 0) {
|
||||
res.status(200).json({
|
||||
day
|
||||
});
|
||||
} else (
|
||||
res.status(500).json({ message: 'Aruppi lost in the shell'})
|
||||
)
|
||||
}).catch((err) =>{
|
||||
console.error(err);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
router.get('/top/:type/:subtype/:page' , (req, res) =>{
|
||||
|
||||
let type = req.params.type;
|
||||
let subtype = req.params.subtype;
|
||||
let page = req.params.page;
|
||||
|
||||
api.top(type, subtype, page)
|
||||
.then(top =>{
|
||||
if (top.length > 0) {
|
||||
res.status(200).json({
|
||||
top
|
||||
});
|
||||
} else (
|
||||
res.status(500).json({ message: 'Aruppi lost in the shell'})
|
||||
)
|
||||
}).catch((err) =>{
|
||||
console.error(err);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
router.get('/allAnimes' , (req, res) =>{
|
||||
|
||||
api.getAllAnimes()
|
||||
.then(animes =>{
|
||||
if (animes.length > 0) {
|
||||
res.status(200).json({
|
||||
animes
|
||||
});
|
||||
} else (
|
||||
res.status(500).json({ message: 'Aruppi lost in the shell'})
|
||||
)
|
||||
}).catch((err) =>{
|
||||
console.error(err);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
router.get('/allDirectory' , (req, res) =>{
|
||||
|
||||
api.getAllDirectory()
|
||||
.then(directory =>{
|
||||
if (directory.length > 0) {
|
||||
res.status(200).json({
|
||||
directory
|
||||
});
|
||||
} else (
|
||||
res.status(500).json({ message: 'Aruppi lost in the shell'})
|
||||
)
|
||||
}).catch((err) =>{
|
||||
console.error(err);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
router.get('/anitakume' , (req, res) =>{
|
||||
|
||||
api.getAnitakume()
|
||||
.then(podcast =>{
|
||||
if (podcast.length > 0) {
|
||||
res.status(200).json({
|
||||
podcast
|
||||
});
|
||||
} else (
|
||||
res.status(500).json({ message: 'Aruppi lost in the shell'})
|
||||
)
|
||||
}).catch((err) =>{
|
||||
console.error(err);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
router.get('/news' , (req, res) =>{
|
||||
|
||||
let pagesRss = [
|
||||
{ url: BASE_KUDASAI, author: 'Kudasai', content: 'content_encoded' },
|
||||
{ url: BASE_PALOMITRON, author: 'Palomitron', content: 'description' },
|
||||
{ url: BASE_RAMENPARADOS, author: 'Ramen para dos', content: 'content' },
|
||||
{ url: BASE_CRUNCHYROLL, author: 'Crunchyroll', content: 'content_encoded' }
|
||||
];
|
||||
|
||||
api.getNews(pagesRss)
|
||||
.then(news =>{
|
||||
if (news.length > 0) {
|
||||
res.status(200).json({
|
||||
news
|
||||
});
|
||||
} else (
|
||||
res.status(500).json({ message: 'Aruppi lost in the shell'})
|
||||
)
|
||||
}).catch((err) =>{
|
||||
console.error(err);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
router.get('/season/:year/:type' , (req, res) =>{
|
||||
|
||||
let year = req.params.year;
|
||||
let type = req.params.type;
|
||||
|
||||
api.season(year, type)
|
||||
.then(season =>{
|
||||
if (season.length > 0) {
|
||||
res.status(200).json({
|
||||
season
|
||||
});
|
||||
} else (
|
||||
res.status(500).json({ message: 'Aruppi lost in the shell'})
|
||||
)
|
||||
}).catch((err) =>{
|
||||
console.error(err);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
router.get('/allSeasons' , (req, res) =>{
|
||||
|
||||
api.allSeasons()
|
||||
.then(archive =>{
|
||||
if (archive.length > 0) {
|
||||
res.status(200).json({
|
||||
archive
|
||||
});
|
||||
} else (
|
||||
res.status(500).json({ message: 'Aruppi lost in the shell'})
|
||||
)
|
||||
}).catch((err) =>{
|
||||
console.error(err);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
router.get('/laterSeasons' , (req, res) =>{
|
||||
|
||||
api.laterSeasons()
|
||||
.then(future =>{
|
||||
if (future.length > 0) {
|
||||
res.status(200).json({
|
||||
future
|
||||
});
|
||||
} else (
|
||||
res.status(500).json({ message: 'Aruppi lost in the shell'})
|
||||
)
|
||||
}).catch((err) =>{
|
||||
console.error(err);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
router.get('/lastEpisodes' , (req, res) =>{
|
||||
|
||||
api.getLastEpisodes()
|
||||
.then(episodes =>{
|
||||
if (episodes.length > 0) {
|
||||
res.status(200).json({
|
||||
episodes
|
||||
});
|
||||
} else (
|
||||
res.status(500).json({ message: 'Aruppi lost in the shell'})
|
||||
)
|
||||
}).catch((err) =>{
|
||||
console.error(err);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
router.get('/movies/:type/:page' , (req, res) =>{
|
||||
|
||||
let type = {url: 'Movies', prop: 'movies'}
|
||||
let subType = req.params.type;
|
||||
let page = req.params.page;
|
||||
|
||||
api.getSpecials(type, subType, page)
|
||||
.then(movies =>{
|
||||
if (movies.length > 0) {
|
||||
res.status(200).json({
|
||||
movies
|
||||
});
|
||||
} else (
|
||||
res.status(500).json({ message: 'Aruppi lost in the shell'})
|
||||
)
|
||||
}).catch((err) =>{
|
||||
console.error(err);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
router.get('/ovas/:type/:page' , (req, res) =>{
|
||||
|
||||
let type = {url: 'Ova', prop: 'ova'}
|
||||
let subType = req.params.type;
|
||||
let page = req.params.page;
|
||||
|
||||
api.getSpecials(type, subType, page)
|
||||
.then(ovas =>{
|
||||
if (ovas.length > 0) {
|
||||
res.status(200).json({
|
||||
ovas
|
||||
});
|
||||
} else (
|
||||
res.status(500).json({ message: 'Aruppi lost in the shell'})
|
||||
)
|
||||
}).catch((err) =>{
|
||||
console.error(err);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
router.get('/specials/:type/:page' , (req, res) =>{
|
||||
|
||||
let type = {url: 'Special', prop: 'special'}
|
||||
let subType = req.params.type;
|
||||
let page = req.params.page;
|
||||
|
||||
api.getSpecials(type, subType, page)
|
||||
.then(specials =>{
|
||||
if (specials.length > 0) {
|
||||
res.status(200).json({
|
||||
specials
|
||||
});
|
||||
} else (
|
||||
res.status(500).json({ message: 'Aruppi lost in the shell'})
|
||||
)
|
||||
}).catch((err) =>{
|
||||
console.error(err);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
router.get('/tv/:type/:page' , (req, res) =>{
|
||||
|
||||
let type = {url: 'Tv', prop: 'tv'}
|
||||
let subType = req.params.type;
|
||||
let page = req.params.page;
|
||||
|
||||
api.getSpecials(type, subType, page)
|
||||
.then(tv =>{
|
||||
if (tv.length > 0) {
|
||||
res.status(200).json({
|
||||
tv
|
||||
});
|
||||
} else (
|
||||
res.status(500).json({ message: 'Aruppi lost in the shell'})
|
||||
)
|
||||
}).catch((err) =>{
|
||||
console.error(err);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
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'})
|
||||
)
|
||||
}).catch((err) =>{
|
||||
console.error(err);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
router.get('/getAnimeServers/:id([^/]+/[^/]+)' , (req, res) =>{
|
||||
|
||||
let id = req.params.id;
|
||||
|
||||
api.getAnimeServers(id)
|
||||
.then(servers =>{
|
||||
if (servers.length > 0) {
|
||||
res.status(200).json({
|
||||
servers
|
||||
});
|
||||
} else (
|
||||
res.status(500).json({ message: 'Aruppi lost in the shell'})
|
||||
)
|
||||
}).catch((err) =>{
|
||||
console.error(err);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
router.get('/search/:title' , (req, res) =>{
|
||||
|
||||
let title = req.params.title;
|
||||
|
||||
api.search(title)
|
||||
.then(search =>{
|
||||
if (search.length > 0) {
|
||||
res.status(200).json({
|
||||
search
|
||||
});
|
||||
} else (
|
||||
res.status(500).json({ message: 'Aruppi lost in the shell'})
|
||||
)
|
||||
}).catch((err) =>{
|
||||
console.error(err);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
router.get('/images/:query' , (req, res) =>{
|
||||
|
||||
let query = { title: req.params.query, count: '51', type: 'images', safesearch: '1', country: 'es_ES', uiv: '4' };
|
||||
|
||||
api.getImages(query)
|
||||
.then(images =>{
|
||||
if (images.length > 0) {
|
||||
res.status(200).json({
|
||||
images
|
||||
});
|
||||
} else (
|
||||
res.status(500).json({ message: 'Aruppi lost in the shell'})
|
||||
)
|
||||
}).catch((err) =>{
|
||||
console.error(err);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
router.get('/videos/:channelId' , (req, res) =>{
|
||||
|
||||
let channelId = { id: req.params.channelId, part: 'snippet,id', order: 'date', maxResults: '50', prop: 'items' };
|
||||
|
||||
api.getYoutubeVideos(channelId)
|
||||
.then(videos =>{
|
||||
if (videos.length > 0) {
|
||||
res.status(200).json({
|
||||
videos
|
||||
});
|
||||
} else (
|
||||
res.status(500).json({ message: 'Aruppi lost in the shell'})
|
||||
)
|
||||
}).catch((err) =>{
|
||||
console.error(err);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
router.get('/radio' , (req, res) =>{
|
||||
|
||||
api.getRadioStations()
|
||||
.then(stations =>{
|
||||
if (stations.length > 0) {
|
||||
res.status(200).json({
|
||||
stations
|
||||
});
|
||||
} else (
|
||||
res.status(500).json({ message: 'Aruppi lost in the shell'})
|
||||
)
|
||||
}).catch((err) =>{
|
||||
console.error(err);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
router.get('/allThemes', (req, res) =>{
|
||||
|
||||
api.getAllThemes()
|
||||
.then(themes =>{
|
||||
if (themes.length > 0) {
|
||||
res.status(200).json({
|
||||
themes
|
||||
});
|
||||
} else (
|
||||
res.status(500).json({ message: 'Aruppi lost in the shell'})
|
||||
)
|
||||
}).catch((err) =>{
|
||||
console.error(err);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
router.get('/themes/:title' , (req, res) =>{
|
||||
|
||||
let title = req.params.title;
|
||||
|
||||
api.getOpAndEd(title)
|
||||
.then(themes =>{
|
||||
if (themes.length > 0) {
|
||||
res.status(200).json({
|
||||
themes
|
||||
});
|
||||
} else (
|
||||
res.status(500).json({ message: 'Aruppi lost in the shell'})
|
||||
)
|
||||
}).catch((err) =>{
|
||||
console.error(err);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
router.get('/themesYear/:year?', (req, res) =>{
|
||||
|
||||
let year = req.params.year;
|
||||
let season = req.params.season
|
||||
|
||||
api.getThemesYear(year, season)
|
||||
.then(themes =>{
|
||||
if (themes.length > 0) {
|
||||
res.status(200).json({
|
||||
themes
|
||||
});
|
||||
} else (
|
||||
res.status(500).json({ message: 'Aruppi lost in the shell'})
|
||||
)
|
||||
}).catch((err) =>{
|
||||
console.error(err);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
router.get('/randomTheme', (req, res) =>{
|
||||
|
||||
api.getRandomTheme()
|
||||
.then(random =>{
|
||||
if (random.length > 0) {
|
||||
res.set('Cache-Control', 'no-store');
|
||||
res.status(200).json({
|
||||
random
|
||||
});
|
||||
} else (
|
||||
res.status(500).json({ message: 'Aruppi lost in the shell'})
|
||||
)
|
||||
}).catch((err) =>{
|
||||
console.error(err);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
router.get('/artists/:id?', (req, res) =>{
|
||||
|
||||
let id = req.params.id;
|
||||
|
||||
api.getArtist(id)
|
||||
.then(artists =>{
|
||||
if (artists.length > 0) {
|
||||
res.status(200).json({
|
||||
artists
|
||||
});
|
||||
} else (
|
||||
res.status(500).json({ message: 'Aruppi lost in the shell'})
|
||||
)
|
||||
}).catch((err) =>{
|
||||
console.error(err);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
router.get('/getByGenres/:genre/:order/:page?' , (req , res) =>{
|
||||
let genre = req.params.genre;
|
||||
let order = req.params.order;
|
||||
let page = req.params.page;
|
||||
api.getAnimeGenres(genre, order , page)
|
||||
.then(animes =>{
|
||||
if (animes.length > 0) {
|
||||
res.status(200).json({
|
||||
animes
|
||||
});
|
||||
} else (
|
||||
res.status(500).json({ message: 'Aruppi lost in the shell'})
|
||||
)
|
||||
}).catch((err) =>{
|
||||
console.error(err);
|
||||
});
|
||||
});
|
||||
|
||||
module.exports = router;
|
|
@ -0,0 +1,21 @@
|
|||
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/',
|
||||
BASE_IVOOX: 'https://www.ivoox.com/podcast-anitakume_fg_f1660716_filtro_1.xml',
|
||||
BASE_KUDASAI: 'https://somoskudasai.com/feed/',
|
||||
BASE_PALOMITRON: 'https://elpalomitron.com/category/animemanga/feed/',
|
||||
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/',
|
||||
BASE_QWANT: 'https://api.qwant.com/search/images?',
|
||||
REDDIT_ANIMETHEMES: 'https://reddit.com/r/AnimeThemes/wiki/',
|
||||
BASE_THEMEMOE: 'https://themes.moe/api/'
|
||||
};
|
|
@ -0,0 +1,306 @@
|
|||
[
|
||||
{
|
||||
"name": "Ghost Anime Radio",
|
||||
"url": "http://animeradio.su:8000/"
|
||||
},
|
||||
{
|
||||
"name": "Vocaloid Radio",
|
||||
"url": "http://curiosity.shoutca.st:8019/stream"
|
||||
},
|
||||
{
|
||||
"name": "NyanServer (J-Trance)",
|
||||
"url": "http://radio.nyan.pw/station/stream"
|
||||
},
|
||||
{
|
||||
"name": "Listen Radio (J-Pop)",
|
||||
"url": "https://listen.moe/stream"
|
||||
},
|
||||
{
|
||||
"name": "Listen Radio (K-Pop)",
|
||||
"url": "https://listen.moe/kpop/stream"
|
||||
},
|
||||
{
|
||||
"name": "Anison FM",
|
||||
"url": "http://pool.anison.fm:9000/AniSonFM(128)"
|
||||
},
|
||||
{
|
||||
"name": "Radio Nami",
|
||||
"url": "https://radionami.com/play_radio.m3u"
|
||||
},
|
||||
{
|
||||
"name": "R/a/dio",
|
||||
"url": "http://relay0.r-a-d.io/main.mp3"
|
||||
},
|
||||
{
|
||||
"name": "Chiru.no",
|
||||
"url": "http://chiru.no:8000/stream.mp3"
|
||||
},
|
||||
{
|
||||
"name": "Vocaloid Radio VRX",
|
||||
"url": "http://vrx.piro.moe:8000/stream-192"
|
||||
},
|
||||
{
|
||||
"name": "Asian Wave Japan",
|
||||
"url": "https://listen1.myradio24.com/7934"
|
||||
},
|
||||
{
|
||||
"name": "Radio Vocaloid",
|
||||
"url": "http://142.4.217.133:9848/stream"
|
||||
},
|
||||
{
|
||||
"name": "Final Fantasy Radio",
|
||||
"url": "http://finalfantasystation.com:8000/stream"
|
||||
},
|
||||
{
|
||||
"name": "Shinsen Radio",
|
||||
"url": "http://shinsen-radio.org:8000/shinsen-radio.128.mp3"
|
||||
},
|
||||
{
|
||||
"name": "Anime Nexus",
|
||||
"url": "http://radio.animenexus.mx:8000/animenexus"
|
||||
},
|
||||
{
|
||||
"name": "Yggdrasil Radio",
|
||||
"url": "http://shirayuki.org:9100/"
|
||||
},
|
||||
{
|
||||
"name": "Eden Radio",
|
||||
"url": "http://edenofthewest.com:8080/eden.mp3"
|
||||
},
|
||||
{
|
||||
"name": "Gensokyo Radio",
|
||||
"url": "http://stream.gensokyoradio.net:8000/"
|
||||
},
|
||||
{
|
||||
"name": "Radio J-Hero",
|
||||
"url": "http://stm1.radiojhero.com:8008/;"
|
||||
},
|
||||
{
|
||||
"name": "Phate Radio",
|
||||
"url": "http://stream.phate.io/phatecc"
|
||||
},
|
||||
{
|
||||
"name": "91.8 The fan",
|
||||
"url": "http://198.27.80.154:8800/live"
|
||||
},
|
||||
{
|
||||
"name": "Radio AOI",
|
||||
"url": "http://radioaoi.pl/stream.m3u"
|
||||
},
|
||||
{
|
||||
"name": "Radio Touhou",
|
||||
"url": "http://www.touhouradio.com/touhouradio.m3u"
|
||||
},
|
||||
{
|
||||
"name": "Radio MultiAnime",
|
||||
"url": "http://67.20.61.70:8301"
|
||||
},
|
||||
{
|
||||
"name": "Radio Fan World Anime",
|
||||
"url": "http://stream.miradio.in:2199/tunein/fanworld.pls"
|
||||
},
|
||||
{
|
||||
"name": "Radio Japan-A",
|
||||
"url": "http://www.japanaradio.com/free/48kaacp.pls"
|
||||
},
|
||||
{
|
||||
"name": "Radio JPopsuki",
|
||||
"url": "http://jpopsuki.fm:2199/tunein/jpopsuki-stream.pls"
|
||||
},
|
||||
{
|
||||
"name": "Radio Hot Mix",
|
||||
"url": "http://hotmixradio-japan.ice.infomaniak.ch/hotmixradio-japan-128.mp3"
|
||||
},
|
||||
{
|
||||
"name": "Dada more Radio",
|
||||
"url": "http://dadamore2.ddo.jp:8000/listen.pls"
|
||||
},
|
||||
{
|
||||
"name": "Initial D World",
|
||||
"url": "http://69.163.186.124:9001/listen.aac"
|
||||
},
|
||||
{
|
||||
"name": "Radio Blast",
|
||||
"url": "http://192.99.150.31:8315/"
|
||||
},
|
||||
{
|
||||
"name": "Kibo FM",
|
||||
"url": "http://listen.kibo.fm:8000/kibofm"
|
||||
},
|
||||
{
|
||||
"name": "Power 945",
|
||||
"url": "http://38.96.148.28:8754/stream"
|
||||
},
|
||||
{
|
||||
"name": "Japan Fans",
|
||||
"url": "http://159.253.37.137:9984/listen.pls"
|
||||
},
|
||||
{
|
||||
"name": "Radio Aniterasu",
|
||||
"url": "http://aniterasu.com:8000/;?1442956789440.mp3"
|
||||
},
|
||||
{
|
||||
"name": "Big B Radio's J-Pop",
|
||||
"url": "http://64.71.79.181:6059/stream"
|
||||
},
|
||||
{
|
||||
"name": "Radio Blue Heron",
|
||||
"url": "http://cp3.digistream.info:8170"
|
||||
},
|
||||
{
|
||||
"name": "Friends Forever",
|
||||
"url": "http://23.29.71.154:8066/"
|
||||
},
|
||||
{
|
||||
"name": "Radio Greek Otaku",
|
||||
"url": "http://192.99.4.210:3684/stream"
|
||||
},
|
||||
{
|
||||
"name": "Radio UR",
|
||||
"url": "http://listen.ur-radio.de/anime.mp3"
|
||||
},
|
||||
{
|
||||
"name": "Radio Anime",
|
||||
"url": "http://stream.animeradio.de/animeradio.mp3"
|
||||
},
|
||||
{
|
||||
"name": "PowerPlay J-Pop",
|
||||
"url": "http://agnes.torontocast.com:8102"
|
||||
},
|
||||
{
|
||||
"name": "Radio Asia Dream",
|
||||
"url": "http://bluford.torontocast.com:8526"
|
||||
},
|
||||
{
|
||||
"name": "J-Pop Kawaii",
|
||||
"url": "http://bb31.sonixcast.com:20002/stream/1/"
|
||||
},
|
||||
{
|
||||
"name": "J-Club HipHop",
|
||||
"url": "http://agnes.torontocast.com:8051"
|
||||
},
|
||||
{
|
||||
"name": "J-Rock",
|
||||
"url": "http://cristina.torontocast.com:8057"
|
||||
},
|
||||
{
|
||||
"name": "J-Pop Sakura",
|
||||
"url": "http://bb31.sonixcast.com:20278/stream/1/"
|
||||
},
|
||||
{
|
||||
"name": "J-Pop Haru Sakura",
|
||||
"url": "http://184.75.223.178:8087/"
|
||||
},
|
||||
{
|
||||
"name": "Radio Ronin",
|
||||
"url": "https://s3.radio.co/sff133d65b/listen"
|
||||
},
|
||||
{
|
||||
"name": "Radio Shinka",
|
||||
"url": "http://5.9.65.9:8171/live"
|
||||
},
|
||||
{
|
||||
"name": "Radio Naihatsu",
|
||||
"url": "http://108.163.223.242:8305/"
|
||||
},
|
||||
{
|
||||
"name": "J-Pop Project",
|
||||
"url": "http://agnes.torontocast.com:8083/"
|
||||
},
|
||||
{
|
||||
"name": "J-idols Project",
|
||||
"url": "http://agnes.torontocast.com:8011/"
|
||||
},
|
||||
{
|
||||
"name": "Radio J1",
|
||||
"url": "https://jenny.torontocast.com:2000/stream/J1HITS"
|
||||
},
|
||||
{
|
||||
"name": "J1 XTRA",
|
||||
"url": "https://jenny.torontocast.com:2000/stream/J1XTRA"
|
||||
},
|
||||
{
|
||||
"name": "J1 GOLD",
|
||||
"url": "https://jenny.torontocast.com:2000/stream/J1GOLD"
|
||||
},
|
||||
{
|
||||
"name": "Animu FM",
|
||||
"url": "http://cast.animu.com.br:9021/stream"
|
||||
},
|
||||
{
|
||||
"name": "Radio Wave Anime",
|
||||
"url": "http://s04.radio-tochka.com:5470/mount"
|
||||
},
|
||||
{
|
||||
"name": "Radio Anime Stream",
|
||||
"url": "https://radioanime.radioca.st/stream"
|
||||
},
|
||||
{
|
||||
"name": "Radio Baka",
|
||||
"url": "http://144.217.203.184:8398/;"
|
||||
},
|
||||
{
|
||||
"name": "Radio Animecol",
|
||||
"url": "http://node-15.zeno.fm/6bfysacxc6quv"
|
||||
},
|
||||
{
|
||||
"name": "JMusic Anime",
|
||||
"url": "http://ample-zeno-24.radiojar.com/ddetxwuhkpeuv"
|
||||
},
|
||||
{
|
||||
"name": "Radio Japanese Music",
|
||||
"url": "http://live.japanesemusicid.com:8000/japanesemusic"
|
||||
},
|
||||
{
|
||||
"name": "Radio Japannext",
|
||||
"url": "https://perseus.shoutca.st/tunein/japannex.pls"
|
||||
},
|
||||
{
|
||||
"name": "Radio Akari",
|
||||
"url": "http://ample-zeno-22.radiojar.com/0t952vqukfeuv"
|
||||
},
|
||||
{
|
||||
"name": "Anime Universe",
|
||||
"url": "http://176.31.241.17:8147/;"
|
||||
},
|
||||
{
|
||||
"name": "Geek Radio Music",
|
||||
"url": "http://stream.zenolive.com/8d0xskxsxxquv"
|
||||
},
|
||||
{
|
||||
"name": "Radio Aniterasu",
|
||||
"url": "http://aniterasuradio.com:8000/;"
|
||||
},
|
||||
{
|
||||
"name": "Radio Akiba",
|
||||
"url": "http://stm24.srvstm.com:9526/;"
|
||||
},
|
||||
{
|
||||
"name": "Radio Caprice",
|
||||
"url": "http://79.111.119.111:8002/anime"
|
||||
},
|
||||
{
|
||||
"name": "Radio Caprice J-Rock",
|
||||
"url": "http://79.111.119.111:8002/jpop"
|
||||
},
|
||||
{
|
||||
"name": "Nihonara!",
|
||||
"url": "http://79.111.119.111:8002/jrock"
|
||||
},
|
||||
{
|
||||
"name": "Radio Opening",
|
||||
"url": "http://5.39.86.120:8000/nihonara_128.mp3"
|
||||
},
|
||||
{
|
||||
"name": "Radio Aewen K-J-Pop",
|
||||
"url": "http://stream.zeno.fm/tza2ayy47qruv"
|
||||
},
|
||||
{
|
||||
"name": "Radio Wkend",
|
||||
"url": "http://209.58.145.135:8031/stream"
|
||||
},
|
||||
{
|
||||
"name": "Nihongo FM",
|
||||
"url": "http://199.180.72.2:9004/stream"
|
||||
}
|
||||
]
|
|
@ -0,0 +1,288 @@
|
|||
const cheerio = require('cheerio');
|
||||
|
||||
const {
|
||||
homgot
|
||||
} = require('../api/apiCall');
|
||||
|
||||
const {
|
||||
REDDIT_ANIMETHEMES
|
||||
} = require('../api/urls');
|
||||
|
||||
class ThemeParser {
|
||||
|
||||
constructor() {}
|
||||
|
||||
async all() {
|
||||
try {
|
||||
this.animes = [];
|
||||
this.$ = await redditocall('year_index');
|
||||
return await this.parseLinks();
|
||||
}
|
||||
catch(err) {
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
async allYears() {
|
||||
try {
|
||||
this.animes = [];
|
||||
this.$ = await redditocall('year_index');
|
||||
return await this.parseYears();
|
||||
}
|
||||
catch(err) {
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
async serie(query) {
|
||||
try {
|
||||
this.animes = [];
|
||||
this.$ = await redditocall('anime_index');
|
||||
return await this.parseSerie(query);
|
||||
}
|
||||
catch(err) {
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
async artists() {
|
||||
try {
|
||||
this.animes = [];
|
||||
this.$ = await redditocall('artist');
|
||||
return await this.parseArtists();
|
||||
}
|
||||
catch(err) {
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
async artist(id) {
|
||||
try {
|
||||
this.animes = [];
|
||||
this.$ = await redditocall(`artist/${id}`);
|
||||
return await this.parseArtist();
|
||||
}
|
||||
catch(err) {
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
async random(query) {
|
||||
try {
|
||||
this.animes = [];
|
||||
this.$ = await redditocall('anime_index');
|
||||
return await this.parseRandom(query);
|
||||
}
|
||||
catch(err) {
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
async year(date) {
|
||||
let animes = [];
|
||||
this.$ = await redditocall(date)
|
||||
this.$('h3').each((i, el) => {
|
||||
let parsed = this.parseAnime(el);
|
||||
parsed.year = date;
|
||||
animes.push(parsed);
|
||||
})
|
||||
return animes;
|
||||
}
|
||||
|
||||
parseRandom() {
|
||||
return new Promise(async resolve => {
|
||||
|
||||
let data = this.$('p a');
|
||||
const origin = '1'
|
||||
let randomize = Math.round(Math.random()*((data.length-1)-origin)+parseInt(origin));
|
||||
|
||||
this.$ = await redditocall(this.$('p a')[randomize].attribs.href.split('/r/AnimeThemes/wiki/')[1].split('#wiki')[0]);
|
||||
|
||||
let rand = Math.round(Math.random()*this.$('h3').length - 1);
|
||||
let parsed = this.parseAnime(this.$('h3')[rand]);
|
||||
resolve(parsed);
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
parseYears(){
|
||||
return new Promise(async resolve => {
|
||||
|
||||
let promises = []
|
||||
let data = this.$('h3 a');
|
||||
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
|
||||
promises.push({
|
||||
id: data[i].children[0].parent.attribs.href.split('/')[4],
|
||||
name: data[i].children[0].data
|
||||
})
|
||||
|
||||
if (i === data.length - 1) {
|
||||
resolve(promises)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
parseArtists(){
|
||||
return new Promise(async resolve => {
|
||||
|
||||
let promises = []
|
||||
let data = this.$('p a').filter(x => x > 0);
|
||||
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
|
||||
promises.push({
|
||||
id: data[i].children[0].parent.attribs.href.split('/')[5],
|
||||
name: data[i].children[0].data
|
||||
})
|
||||
|
||||
if (i === data.length - 1) {
|
||||
resolve(promises)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
parseArtist(){
|
||||
return new Promise(async resolve => {
|
||||
|
||||
let promises = []
|
||||
let data = this.$('h3');
|
||||
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
|
||||
let parsed = await this.parseAnime(data[i])
|
||||
promises.push(parsed)
|
||||
|
||||
if (i === data.length - 1) {
|
||||
resolve(promises)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
parseSerie(query){
|
||||
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) {
|
||||
|
||||
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) {
|
||||
let parsed = this.parseAnime(this.$('h3')[i]);
|
||||
resolve(parsed);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
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);
|
||||
if(i === years.length - 1) {
|
||||
resolve(this.animes);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
parseAnime(dat) {
|
||||
let el = this.$(dat).children('a');
|
||||
let title = el.text();
|
||||
let malId = el.attr('href').split('/')[4];
|
||||
let next = this.$(dat).next();
|
||||
|
||||
let theme = {
|
||||
id: malId,
|
||||
title
|
||||
}
|
||||
|
||||
if (next.prop("tagName") === "P") {
|
||||
theme.themes = this.parseTable(next.next());
|
||||
} else if (next.prop("tagName") === "TABLE") {
|
||||
theme.themes = this.parseTable(next);
|
||||
}
|
||||
|
||||
return theme;
|
||||
}
|
||||
|
||||
parseTable(table) {
|
||||
if (table.prop('tagName') !== "TABLE") {
|
||||
return this.parseTable(table.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();
|
||||
|
||||
themes.push({
|
||||
name,
|
||||
link,
|
||||
desc: linkDesc,
|
||||
type: (name.startsWith('OP') ? 'opening' : 'ending'),
|
||||
episodes,
|
||||
notes
|
||||
})
|
||||
})
|
||||
|
||||
return themes;
|
||||
}
|
||||
}
|
||||
|
||||
async function redditocall(href) {
|
||||
let options = { parse: true }
|
||||
let resp = await homgot(REDDIT_ANIMETHEMES + href + ".json", options)
|
||||
|
||||
return cheerio.load(getHTML(resp.data.content_html));
|
||||
}
|
||||
|
||||
function getHTML(str) {
|
||||
let html = replaceAll(str, "<", "<")
|
||||
html = replaceAll(html, ">", ">")
|
||||
return html;
|
||||
}
|
||||
|
||||
function replaceAll(str, find, replace) {
|
||||
return str.replace(new RegExp(find, 'g'), replace);
|
||||
}
|
||||
|
||||
module.exports = ThemeParser;
|
|
@ -0,0 +1,698 @@
|
|||
const {
|
||||
BASE_ANIMEFLV, BASE_JIKAN, BASE_EPISODE_IMG_URL, SEARCH_URL, SEARCH_DIRECTORY, BASE_ARUPPI, BASE_JKANIME, JKANIME_URL
|
||||
} = require('../api/urls.js');
|
||||
|
||||
const {
|
||||
homgot
|
||||
} = require('../api/apiCall.js');
|
||||
|
||||
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 episodes = $('div#reproductor-box li');
|
||||
const serverNames = [];
|
||||
let servers = [];
|
||||
|
||||
episodes.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: episodes.length} , (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 = [];
|
||||
for(let server in servers) {
|
||||
serverList.push({
|
||||
id: serverNames[server].toLowerCase(),
|
||||
url: await getVideoURL(servers[server].iframe),
|
||||
direct: true
|
||||
});
|
||||
}
|
||||
|
||||
serverList = serverList.filter(x => x.id !== 'xtreme s' && x.id !== 'desuka' );
|
||||
|
||||
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 = 1; 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 animeflvGenres = async (id) => {
|
||||
|
||||
const promises = [];
|
||||
|
||||
let options = { scrapy: true }
|
||||
let $ = await homgot(`${BASE_ANIMEFLV}${id}`, options);
|
||||
|
||||
$('main.Main section.WdgtCn nav.Nvgnrs a').each((index, element) => {
|
||||
const $element = $(element);
|
||||
const genre = $element.attr('href').split('=')[1] || null;
|
||||
promises.push(genre);
|
||||
});
|
||||
|
||||
return promises;
|
||||
|
||||
}
|
||||
|
||||
const animeflvInfo = async (id, index) => {
|
||||
|
||||
let poster = ""
|
||||
let banner = ""
|
||||
let synopsis = ""
|
||||
let rating = ""
|
||||
let debut = ""
|
||||
let type = ""
|
||||
let $
|
||||
|
||||
try {
|
||||
|
||||
let options = { scrapy: true }
|
||||
$ = await homgot(`${BASE_ANIMEFLV}anime/${id}`, options);
|
||||
|
||||
const scripts = $('script');
|
||||
const anime_info_ids = [];
|
||||
const anime_eps_data = [];
|
||||
const animeExtraInfo = [];
|
||||
const genres = [];
|
||||
let listByEps;
|
||||
|
||||
poster = `${BASE_ANIMEFLV}` + $('body div div div div div aside div.AnimeCover div.Image figure img').attr('src')
|
||||
banner = poster.replace('covers', 'banners').trim();
|
||||
synopsis = $('body div div div div div main section div.Description p').text().trim();
|
||||
rating = $('body div div div.Ficha.fchlt div.Container div.vtshr div.Votes span#votes_prmd').text();
|
||||
debut = $('body div.Wrapper div.Body div div.Container div.BX.Row.BFluid.Sp20 aside.SidebarA.BFixed p.AnmStts').text();
|
||||
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
|
||||
|
||||
if (anime_info_ids.length > 0) {
|
||||
if (anime_info_ids[0].length === 4) {
|
||||
nextEpisodeDate = anime_info_ids[0][3]
|
||||
} else {
|
||||
nextEpisodeDate = 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) => {
|
||||
|
||||
try {
|
||||
let options = { parse: true }
|
||||
|
||||
const res = await homgot(`${BASE_JIKAN}search/anime?q=${title}`, options);
|
||||
const matchAnime = res.results.filter(x => x.title === title);
|
||||
const malId = matchAnime[0].mal_id;
|
||||
|
||||
if (typeof matchAnime[0].mal_id === 'undefined') return null;
|
||||
|
||||
const data = await homgot(`${BASE_JIKAN}anime/${malId}/characters_staff`, options);
|
||||
let body = 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);
|
||||
} catch (e) {
|
||||
console.log(e.message)
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
const getAnimeVideoPromo = async (title) => {
|
||||
|
||||
try {
|
||||
let options = { parse: true }
|
||||
const res = await homgot(`${BASE_JIKAN}search/anime?q=${title}`, options);
|
||||
const matchAnime = res.results.filter(x => x.title === title);
|
||||
const malId = matchAnime[0].mal_id;
|
||||
|
||||
if (typeof matchAnime[0].mal_id === 'undefined') return null;
|
||||
|
||||
const data = await homgot(`${BASE_JIKAN}anime/${malId}/videos`, options);
|
||||
const body = data.promo;
|
||||
const promises = [];
|
||||
|
||||
body.map(doc => {
|
||||
promises.push({
|
||||
title: doc.title,
|
||||
previewImage: doc.image_url,
|
||||
videoURL: doc.video_url
|
||||
});
|
||||
});
|
||||
|
||||
return Promise.all(promises);
|
||||
} catch (e) {
|
||||
console.log(e.message)
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
const animeExtraInfo = async (title) => {
|
||||
|
||||
try {
|
||||
|
||||
let options = { parse: true }
|
||||
const res = await homgot(`${BASE_JIKAN}search/anime?q=${title}`, options);
|
||||
const matchAnime = res.results.filter(x => x.title === title);
|
||||
const malId = matchAnime[0].mal_id;
|
||||
|
||||
if (typeof matchAnime[0].mal_id === 'undefined') return null;
|
||||
|
||||
const data = await homgot(`${BASE_JIKAN}anime/${malId}`, options);
|
||||
const body = Array(data);
|
||||
const promises = [];
|
||||
|
||||
body.map(doc => {
|
||||
|
||||
let airDay = {
|
||||
'mondays': 'Lunes',
|
||||
'monday': 'Lunes',
|
||||
'tuesdays': 'Martes',
|
||||
'tuesday': 'Martes',
|
||||
'wednesdays': 'Miércoles',
|
||||
'wednesday': 'Miércoles',
|
||||
'thursdays': 'Jueves',
|
||||
'thursday': 'Jueves',
|
||||
'fridays': 'Viernes',
|
||||
'friday': 'Viernes',
|
||||
'saturdays': 'Sábados',
|
||||
'saturday': 'Sábados',
|
||||
'sundays': 'Domingos',
|
||||
'sunday': 'Domingos',
|
||||
'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,
|
||||
totalEpisodes: doc.episodes,
|
||||
aired: {
|
||||
from: doc.aired.from,
|
||||
to: doc.aired.to
|
||||
},
|
||||
duration: doc.duration.split('per')[0],
|
||||
rank: doc.rank,
|
||||
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,
|
||||
openingThemes: doc.opening_themes || null,
|
||||
endingThemes: doc.ending_themes || null
|
||||
});
|
||||
});
|
||||
return Promise.all(promises);
|
||||
|
||||
} catch (e) {
|
||||
console.log(e.message)
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
const imageUrlToBase64 = async (url) => {
|
||||
let img = await homgot(url)
|
||||
return img.rawBody.toString('base64');
|
||||
};
|
||||
|
||||
const helper = async () => {}
|
||||
|
||||
const searchAnime = async (query) => {
|
||||
|
||||
let $
|
||||
let promises = []
|
||||
|
||||
const jkAnimeTitles = [
|
||||
{ title: 'BNA', search: 'BNA'},
|
||||
{ title: 'The God of High School', search: 'The god' },
|
||||
{ title: 'Ansatsu Kyoshitsu', search: 'Assassination Classroom' },
|
||||
];
|
||||
|
||||
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) => {
|
||||
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);
|
||||
|
||||
};
|
||||
|
||||
const transformUrlServer = async (urlReal) => {
|
||||
|
||||
let res
|
||||
const promises = []
|
||||
|
||||
for (const index in urlReal) {
|
||||
if (urlReal[index].server === 'amus' || urlReal[index].server === 'natsuki') {
|
||||
|
||||
let options = { parse: true }
|
||||
res = await homgot(urlReal[index].code.replace("embed", "check"), options);
|
||||
|
||||
urlReal[index].code = res.file || null
|
||||
urlReal[index].direct = true
|
||||
} else if (urlReal[index].server === 'gocdn' ) {
|
||||
urlReal[index].code = `https://s1.streamium.xyz/gocdn.php?v=${urlReal[index].code.split('/player_gocdn.html#')[1]}`
|
||||
urlReal[index].direct = true
|
||||
}
|
||||
}
|
||||
|
||||
urlReal.map(doc => {
|
||||
promises.push({
|
||||
id: doc.title.toLowerCase(),
|
||||
url: doc.code,
|
||||
direct: doc.direct || false
|
||||
});
|
||||
});
|
||||
|
||||
return promises;
|
||||
}
|
||||
|
||||
const obtainPreviewNews = (encoded) => {
|
||||
|
||||
let image;
|
||||
|
||||
if (encoded.includes('src="https://img1.ak.crunchyroll.com/')) {
|
||||
image = `https://img1.ak.crunchyroll.com/${encoded.split('https://img1.ak.crunchyroll.com/')[1].split('.jpg')[0]}.jpg`
|
||||
} else if (encoded.includes('<img title=')) {
|
||||
image = encoded.substring(encoded.indexOf("<img title=\""), encoded.indexOf("\" alt")).split('src=\"')[1]
|
||||
} else if (encoded.includes('<img src=')) {
|
||||
image = encoded
|
||||
.substring(encoded.indexOf("<img src=\""), encoded.indexOf("\" alt"))
|
||||
.substring(10).replace("http", "https")
|
||||
.replace("httpss", "https")
|
||||
} else if (encoded.includes('<img')) {
|
||||
image = encoded.split("src=")[1].split(" class=")[0].replace("\"", '').replace('\"', '')
|
||||
} else if (encoded.includes('https://www.youtube.com/embed/')) {
|
||||
let getSecondThumb = encoded.split('https://www.youtube.com/embed/')[1].split('?feature')[0]
|
||||
image = `https://img.youtube.com/vi/${getSecondThumb}/0.jpg`
|
||||
} else if (encoded.includes('https://www.dailymotion.com/')) {
|
||||
let getDailymotionThumb = encoded
|
||||
.substring(encoded.indexOf("\" src=\""), encoded.indexOf("\" a"))
|
||||
.substring(47)
|
||||
image = `https://www.dailymotion.com/thumbnail/video/${getDailymotionThumb}`
|
||||
} else {
|
||||
let number = Math.floor(Math.random() * 30);
|
||||
image = `${BASE_ARUPPI}news/${number}.png`
|
||||
}
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
const structureThemes = async (body, indv) => {
|
||||
|
||||
const promises = []
|
||||
let themes
|
||||
|
||||
if (indv === true) {
|
||||
themes = await getThemesData(body.themes)
|
||||
|
||||
promises.push({
|
||||
title: body.title,
|
||||
year: body.year,
|
||||
themes: themes,
|
||||
});
|
||||
|
||||
} else {
|
||||
|
||||
for (let i = 0; i <= body.length - 1; i++) {
|
||||
|
||||
themes = await getThemesData(body[i].themes)
|
||||
|
||||
promises.push({
|
||||
title: body[i].title,
|
||||
year: body[i].year,
|
||||
themes: themes,
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return promises;
|
||||
|
||||
};
|
||||
|
||||
|
||||
const getThemesData = async (themes) => {
|
||||
|
||||
let promises = []
|
||||
|
||||
for (let i = 0; i <= themes.length - 1; i++) {
|
||||
|
||||
promises.push({
|
||||
title: themes[i].name.split('"')[1] || 'Remasterización',
|
||||
type: themes[i].name.split('"')[0] || 'OP/ED',
|
||||
episodes: themes[i].episodes || null,
|
||||
video: themes[i].link
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
return promises;
|
||||
|
||||
};
|
||||
|
||||
const getThemes = async (themes) => {
|
||||
|
||||
let promises = []
|
||||
|
||||
themes.map(doc => {
|
||||
|
||||
promises.push({
|
||||
name: doc.themeName,
|
||||
type: doc.themeType,
|
||||
video: doc.mirror.mirrorURL
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
return promises;
|
||||
|
||||
};
|
||||
|
||||
const getAnimes = async () => {
|
||||
let options = { parse: true }
|
||||
return await homgot(`${BASE_ANIMEFLV}api/animes/list`, options);
|
||||
};
|
||||
|
||||
|
||||
const getDirectory = async () => {
|
||||
|
||||
let $
|
||||
let promises = []
|
||||
|
||||
let options = { scrapy: true }
|
||||
$ = await homgot(`${SEARCH_URL}`, options);
|
||||
const lastPage = $('body div.Wrapper div.Container main div.NvCnAnm ul li a')[11].children[0].data
|
||||
|
||||
for (let i = 1; i <= lastPage; i++) {
|
||||
|
||||
let options = { scrapy: true }
|
||||
$ = await homgot(`${SEARCH_DIRECTORY}${i}`, 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
|
||||
})));
|
||||
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
return Promise.all(promises);
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
jkanimeInfo,
|
||||
animeflvGenres,
|
||||
animeflvInfo,
|
||||
getAnimeCharacters,
|
||||
getAnimeVideoPromo,
|
||||
animeExtraInfo,
|
||||
imageUrlToBase64,
|
||||
searchAnime,
|
||||
transformUrlServer,
|
||||
obtainPreviewNews,
|
||||
structureThemes,
|
||||
getThemes,
|
||||
getAnimes,
|
||||
getDirectory,
|
||||
helper,
|
||||
videoServersJK
|
||||
}
|
Loading…
Reference in New Issue