Compare commits

..

No commits in common. 'v4' and 'v4.1.5' have entirely different histories.
v4 ... v4.1.5

@ -1,4 +1,4 @@
# **Aruppi API** (v4.2.2) # **Aruppi API** (v4.1.5)
> This API has everything about Japan, from anime, music, radio, images, videos ... to japanese culture > This API has everything about Japan, from anime, music, radio, images, videos ... to japanese culture
> >
@ -116,7 +116,7 @@ Currently the Aruppi app on Android is already using the v4.x.x API services fro
</td> </td>
<td align="center"> <td align="center">
<a href="https://github.com/Fmaldonado6/Akiyama"> <a href="https://github.com/Fmaldonado6/Akiyama">
<img src="https://raw.githubusercontent.com/Fmaldonado6/Akiyama/master/images/logo/logo.png" width="75px;" alt="Jeluchu"/><br /> <img src="https://raw.githubusercontent.com/Fmaldonado6/Akiyama/master/images/logo/web-logo.png" width="75px;" alt="Jeluchu"/><br />
<sub> <sub>
<b>Akiyama</b> <b>Akiyama</b>
</sub> </sub>
@ -156,4 +156,4 @@ There are also **people who have made contributions** and therefore it is also i
- [Jéluchu](https://github.com/Jeluchu) (Multiplatform Developer, designer, and others) - [Jéluchu](https://github.com/Jeluchu) (Multiplatform Developer, designer, and others)
- [Capitanwesler](https://github.com/capitanwesler) (Backend developer, web developer and others) - [Capitanwesler](https://github.com/capitanwesler) (Backend developer, web developer and others)
Copyright © 2022 [Jéluchu](https://about.jeluchu.com/). Copyright © 2021 [Jéluchu](https://about.jeluchu.com/).

7496
package-lock.json generated

File diff suppressed because it is too large Load Diff

@ -1,6 +1,6 @@
{ {
"name": "aruppi", "name": "aruppi",
"version": "4.2.2", "version": "4.1.5",
"description": "Aruppi is a custom API to obtain data from the Japanese culture for the mobile app", "description": "Aruppi is a custom API to obtain data from the Japanese culture for the mobile app",
"main": "./src/api/api.ts", "main": "./src/api/api.ts",
"scripts": { "scripts": {
@ -54,11 +54,12 @@
"compose-middleware": "^5.0.1", "compose-middleware": "^5.0.1",
"cors": "^2.8.5", "cors": "^2.8.5",
"dotenv": "^8.2.0", "dotenv": "^8.2.0",
"express": "^4.17.3", "express": "^4.17.1",
"got": "^11.8.5", "got": "^11.8.2",
"helmet": "^4.5.0", "helmet": "^4.5.0",
"mongodb": "^3.6.6", "mongodb": "^3.6.6",
"mongoose": "^5.13.15", "mongoose": "^5.12.5",
"node-html-parser": "^5.1.0",
"redis": "^3.1.2", "redis": "^3.1.2",
"rss-parser": "^3.12.0", "rss-parser": "^3.12.0",
"tough-cookie": "^4.0.0", "tough-cookie": "^4.0.0",

@ -81,7 +81,7 @@ interface Movie {
export default class AnimeController { export default class AnimeController {
async schedule(req: Request, res: Response, next: NextFunction) { async schedule(req: Request, res: Response, next: NextFunction) {
const { day } = req.params; const { day } = req.params;
let info: any; let data: any;
try { try {
if (redisClient.connected) { if (redisClient.connected) {
@ -96,7 +96,7 @@ export default class AnimeController {
} }
} }
info = await requestGot(`${urls.BASE_JIKAN}schedules?filter=${day}`, { data = await requestGot(`${urls.BASE_JIKAN}schedule/${day}`, {
parse: true, parse: true,
scrapy: false, scrapy: false,
}); });
@ -104,10 +104,10 @@ export default class AnimeController {
return next(err); return next(err);
} }
const animeList: Schedule[] = info.data.map((item: any) => ({ const animeList: Schedule[] = data[day].map((item: Schedule) => ({
title: item.titles.find((x: { type: string; }) => x.type === "Default").title, title: item.title,
malid: item.mal_id, malid: item.mal_id,
image: item.images.jpg.image_url, image: item.image_url,
})); }));
if (animeList.length > 0) { if (animeList.length > 0) {
@ -119,11 +119,11 @@ export default class AnimeController {
JSON.stringify({ day: animeList }), JSON.stringify({ day: animeList }),
); );
/* After 6hrs expire the key. */ /* After 24hrs expire the key. */
redisClient.expire( redisClient.expireat(
`schedule_${hashStringMd5(day)}`, `schedule_${hashStringMd5(day)}`,
+ 21600, parseInt(`${+new Date() / 1000}`, 10) + 7200,
); );
} }
@ -137,7 +137,7 @@ export default class AnimeController {
async top(req: Request, res: Response, next: NextFunction) { async top(req: Request, res: Response, next: NextFunction) {
const { type, subtype, page } = req.params; const { type, subtype, page } = req.params;
let info: any; let data: any;
try { try {
if (redisClient.connected) { if (redisClient.connected) {
@ -161,12 +161,12 @@ export default class AnimeController {
} }
if (subtype !== undefined) { if (subtype !== undefined) {
info = await requestGot( data = await requestGot(
`${urls.BASE_JIKAN}top/${type}?filter=${subtype}&page=${page}`, `${urls.BASE_JIKAN}top/${type}/${page}/${subtype}`,
{ parse: true, scrapy: false }, { parse: true, scrapy: false },
); );
} else { } else {
info = await requestGot(`${urls.BASE_JIKAN}top/${type}?page=${page}`, { data = await requestGot(`${urls.BASE_JIKAN}top/${type}/${page}`, {
parse: true, parse: true,
scrapy: false, scrapy: false,
}); });
@ -175,12 +175,11 @@ export default class AnimeController {
return next(err); return next(err);
} }
const top: Top[] = info.data.map((item: any, index: number) => ({ const top: Top[] = data.top.map((item: Top) => ({
// A little hacky way to fix null ranks rank: item.rank,
rank: item.rank || index + 1 + (info.pagination.current_page-1)*info.pagination.items.per_page, title: item.title,
title: item.titles.find((x: { type: string; }) => x.type === "Default").title,
url: item.url, url: item.url,
image_url: item.images.jpg.image_url, image_url: item.image_url,
type: type, type: type,
subtype: subtype, subtype: subtype,
page: page, page: page,
@ -230,7 +229,6 @@ export default class AnimeController {
data = await requestGot(`${urls.BASE_ANIMEFLV}api/animes/list`, { data = await requestGot(`${urls.BASE_ANIMEFLV}api/animes/list`, {
parse: true, parse: true,
scrapy: false, scrapy: false,
spoof: true,
}); });
} catch (err) { } catch (err) {
return next(err); return next(err);
@ -270,9 +268,9 @@ export default class AnimeController {
} }
} }
lastEpisodes = await requestGot(`${urls.BASE_ARUPPI_MONOSCHINOS}lastest`, { lastEpisodes = await requestGot(`${urls.BASE_ARUPPI_MONOSCHINOS}`, {
scrapy: false, scrapy: true,
parse: true, parse: false,
}); });
} catch (err) { } catch (err) {
@ -284,7 +282,7 @@ export default class AnimeController {
id: `ver/${anime.id}`, id: `ver/${anime.id}`,
title: anime.title, title: anime.title,
image: anime.image, image: anime.image,
episode: anime.no, episode: anime.episode,
}); });
} }

@ -104,7 +104,7 @@ export default class DirectoryController {
async getSeason(req: Request, res: Response, next: NextFunction) { async getSeason(req: Request, res: Response, next: NextFunction) {
const { year, type } = req.params; const { year, type } = req.params;
let info: any; let data: any;
try { try {
if (redisClient.connected) { if (redisClient.connected) {
@ -119,7 +119,7 @@ export default class DirectoryController {
} }
} }
info = await requestGot(`${urls.BASE_JIKAN}seasons/${year}/${type}`, { data = await requestGot(`${urls.BASE_JIKAN}season/${year}/${type}`, {
scrapy: false, scrapy: false,
parse: true, parse: true,
}); });
@ -127,10 +127,10 @@ export default class DirectoryController {
return next(err); return next(err);
} }
const season: TypeAnime[] = info.data.map((item: any) => { const season: TypeAnime[] = data.anime.map((item: any) => {
return { return {
title: item.titles.find((x: { type: string; }) => x.type === "Default").title, title: item.title,
image: item.images.jpg.image_url, image: item.image_url,
genres: item.genres.map((genre: any) => genre.name), genres: item.genres.map((genre: any) => genre.name),
}; };
}); });
@ -161,7 +161,7 @@ export default class DirectoryController {
} }
async allSeasons(req: Request, res: Response, next: NextFunction) { async allSeasons(req: Request, res: Response, next: NextFunction) {
let info: any; let data: any;
try { try {
if (redisClient.connected) { if (redisClient.connected) {
@ -176,7 +176,7 @@ export default class DirectoryController {
} }
} }
info = await requestGot(`${urls.BASE_JIKAN}seasons`, { data = await requestGot(`${urls.BASE_JIKAN}season/archive`, {
parse: true, parse: true,
scrapy: false, scrapy: false,
}); });
@ -184,7 +184,7 @@ export default class DirectoryController {
return next(err); return next(err);
} }
const archive: Archive[] = info.data.map((item: any) => { const archive: Archive[] = data.archive.map((item: any) => {
return { return {
year: item.year, year: item.year,
seasons: item.seasons, seasons: item.seasons,
@ -215,7 +215,7 @@ export default class DirectoryController {
} }
async laterSeasons(req: Request, res: Response, next: NextFunction) { async laterSeasons(req: Request, res: Response, next: NextFunction) {
let info: any; let data: any;
try { try {
if (redisClient.connected) { if (redisClient.connected) {
@ -230,7 +230,7 @@ export default class DirectoryController {
} }
} }
info = await requestGot(`${urls.BASE_JIKAN}seasons/upcoming`, { data = await requestGot(`${urls.BASE_JIKAN}season/later`, {
parse: true, parse: true,
scrapy: false, scrapy: false,
}); });
@ -238,10 +238,10 @@ export default class DirectoryController {
return next(err); return next(err);
} }
const future: Season[] = info.data.map((item: any) => { const future: Season[] = data.anime.map((item: any) => {
return { return {
title: item.titles.find((x: { type: string; }) => x.type === "Default").title, title: item.title,
image: item.images.jpg.image_url, image: item.image_url,
malink: item.url, malink: item.url,
}; };
}); });
@ -294,7 +294,6 @@ export default class DirectoryController {
const extraInfo: any = await animeExtraInfo(resultQuery!.mal_id); const extraInfo: any = await animeExtraInfo(resultQuery!.mal_id);
resultAnime = { resultAnime = {
//aruppi_key: hashStringMd5(title),
title: resultQuery?.title, title: resultQuery?.title,
poster: resultQuery?.poster, poster: resultQuery?.poster,
synopsis: resultQuery?.description, synopsis: resultQuery?.description,

@ -234,7 +234,7 @@ export default class UtilsController {
`${urls.BASE_QWANT}t=images&q=${encodeURIComponent( `${urls.BASE_QWANT}t=images&q=${encodeURIComponent(
title, title,
)}&count=51&locale=es_ES&safesearch=1`, )}&count=51&locale=es_ES&safesearch=1`,
{ scrapy: false, parse: true, spoof: true, }, { scrapy: false, parse: true },
); );
} catch (err) { } catch (err) {
return next(err); return next(err);
@ -243,8 +243,8 @@ export default class UtilsController {
const results: any[] = data.data.result.items.map((item: any) => { const results: any[] = data.data.result.items.map((item: any) => {
return { return {
type: item.thumb_type, type: item.thumb_type,
thumbnail: `${item.thumbnail}`, thumbnail: `https:${item.thumbnail}`,
fullsize: `${item.media_fullsize}`, fullsize: `https:${item.media_fullsize}`,
}; };
}); });
@ -637,7 +637,6 @@ export default class UtilsController {
data = await requestGot(`${urls.BASE_THEMEMOE}roulette`, { data = await requestGot(`${urls.BASE_THEMEMOE}roulette`, {
parse: true, parse: true,
scrapy: false, scrapy: false,
spoof: true,
}); });
} catch (err) { } catch (err) {
return next(err); return next(err);

@ -26,7 +26,7 @@ routes.get('/api/v4/', (req: Request, res: Response) => {
res.json({ res.json({
message: 'Aruppi /api - 🎏', message: 'Aruppi /api - 🎏',
author: 'Jéluchu', author: 'Jéluchu',
version: '4.2.2', version: '4.1.5',
credits: 'The bitch loves /apis that offers data to Aruppi App', credits: 'The bitch loves /apis that offers data to Aruppi App',
entries: [ entries: [
{ {

@ -285,7 +285,6 @@ async function redditocall(href: string) {
const resp = await requestGot(urls.REDDIT_ANIMETHEMES + href + '.json', { const resp = await requestGot(urls.REDDIT_ANIMETHEMES + href + '.json', {
parse: true, parse: true,
scrapy: false, scrapy: false,
spoof: true,
}); });
return cheerio.load(getHTML(resp.data.content_html)); return cheerio.load(getHTML(resp.data.content_html));

@ -1,52 +1,28 @@
import got from 'got'; import got from 'got';
import cheerio from 'cheerio'; import cheerio from 'cheerio';
import { CookieJar } from 'tough-cookie'; import { CookieJar } from 'tough-cookie';
// @ts-ignore
import * as got_pjson from 'got/package.json'
const pjson = require('../../package.json');
const cookieJar = new CookieJar(); const cookieJar = new CookieJar();
const aruppi_options: any = {
cookieJar,
'headers': {
'user-agent': `Aruppi-API/${pjson.version} ${got_pjson.name}/${got_pjson.version}`,
'x-client': 'aruppi-api'
},
};
interface Options { interface Options {
scrapy?: boolean, scrapy: boolean;
parse?: boolean, parse: boolean;
spoof?: boolean
} }
export const requestGot = async ( export const requestGot = async (
url: string, url: string,
options?: Options, options?: Options,
): Promise<any> => { ): Promise<any> => {
const got_options: any = {...got.defaults.options, ...aruppi_options} if (options !== undefined) {
if (options) { if (options.scrapy) {
if (options.spoof != null) { const response = await got(url, { cookieJar });
got_options.headers["user-agent"] = "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:71.0) Gecko/20100101 Firefox/69.0"; return await cheerio.load(response.body);
delete got_options.headers['x-client']; }
if (!options.spoof)
got_options.headers['user-agent'] = got.defaults.options.headers['user-agent'];
} else if (process.env.ALPI_KEY && (new URL(url)).hostname.match(/\.jeluchu\.xyz$/)) {
got_options.headers['x-aruppi-key'] = process.env.ALPI_KEY;
}
if (options.scrapy) {
const response = await got(url, got_options);
return cheerio.load(response.body);
}
if (options.parse) { if (options.parse) {
got_options.responseType = 'json'; return await got(url, { cookieJar }).json();
const response = await got(url, got_options);
return response.body;
}
} }
const response = await got.get(url, got_options); } else {
return response; return await got.get(url, { cookieJar });
}
}; };

@ -7,8 +7,9 @@ export default {
BASE_ANIMEFLV_JELU: 'https://aruppi.jeluchu.xyz/apis/animeflv/v1/', BASE_ANIMEFLV_JELU: 'https://aruppi.jeluchu.xyz/apis/animeflv/v1/',
BASE_YOUTUBE: 'https://aruppi.jeluchu.xyz/api/Youtube/?channelId=', BASE_YOUTUBE: 'https://aruppi.jeluchu.xyz/api/Youtube/?channelId=',
BASE_YOUTUBE_PLAYLIST: 'https://aruppi.jeluchu.xyz/api/Youtube/playlist/?playlistId=', BASE_YOUTUBE_PLAYLIST: 'https://aruppi.jeluchu.xyz/api/Youtube/playlist/?playlistId=',
BASE_JIKAN: 'https://aruppi.jeluchu.xyz/apis/jikan/v4/', BASE_JIKAN: 'https://aruppi.jeluchu.xyz/apis/jikan/v3/',
BASE_IVOOX: 'https://www.ivoox.com/podcast-anitakume_fg_f1660716_filtro_1.xml', BASE_IVOOX:
'https://www.ivoox.com/podcast-anitakume_fg_f1660716_filtro_1.xml',
BASE_KUDASAI: 'https://somoskudasai.com/feed/', BASE_KUDASAI: 'https://somoskudasai.com/feed/',
BASE_RAMENPARADOS: 'https://ramenparados.com/category/noticias/anime/feed/', BASE_RAMENPARADOS: 'https://ramenparados.com/category/noticias/anime/feed/',
BASE_CRUNCHYROLL: 'https://www.crunchyroll.com/newsrss?lang=esES', BASE_CRUNCHYROLL: 'https://www.crunchyroll.com/newsrss?lang=esES',
@ -16,7 +17,7 @@ export default {
ANIMEFLV_SEARCH: 'https://animeflv.net/browse?', ANIMEFLV_SEARCH: 'https://animeflv.net/browse?',
SEARCH_DIRECTORY: 'https://animeflv.net/browse?order=title&page=', SEARCH_DIRECTORY: 'https://animeflv.net/browse?order=title&page=',
BASE_EPISODE_IMG_URL: 'https://cdn.animeflv.net/screenshots/', BASE_EPISODE_IMG_URL: 'https://cdn.animeflv.net/screenshots/',
BASE_QWANT: 'https://api.qwant.com/v3/search/images?', BASE_QWANT: 'https://api.qwant.com/search/images?',
REDDIT_ANIMETHEMES: 'https://reddit.com/r/AnimeThemes/wiki/', REDDIT_ANIMETHEMES: 'https://reddit.com/r/AnimeThemes/wiki/',
BASE_THEMEMOE: 'https://themes.moe/api/', BASE_THEMEMOE: 'https://themes.moe/api/',
BASE_ARUPPI_MONOSCHINOS: 'https://aruppi.jeluchu.xyz/apis/monoschinos/', BASE_ARUPPI_MONOSCHINOS: 'https://aruppi.jeluchu.xyz/apis/monoschinos/',

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save