mirror of https://github.com/aruppi/aruppi-api.git
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
524 lines
14 KiB
TypeScript
524 lines
14 KiB
TypeScript
import { NextFunction, Request, Response } from 'express';
|
|
import Parser from 'rss-parser';
|
|
import urls from '../utils/urls';
|
|
import { obtainPreviewNews } from '../utils/obtainPreviews';
|
|
import { requestGot } from '../utils/requestCall';
|
|
import RadioStationModel, {
|
|
RadioStation,
|
|
} from '../database/models/radiostation.model';
|
|
import ThemeModel, { Theme } from '../database/models/theme.model';
|
|
import ThemeParser from '../utils/animeTheme';
|
|
import { structureThemes } from '../utils/util';
|
|
import { getThemes } from '../utils/util';
|
|
|
|
/*
|
|
UtilsController - controller to parse the
|
|
feed and get news, all with scraping and
|
|
parsing RSS.
|
|
*/
|
|
|
|
const themeParser = new ThemeParser();
|
|
|
|
type CustomFeed = {
|
|
foo: string;
|
|
};
|
|
type CustomItem = {
|
|
bar: number;
|
|
itunes: { duration: string; image: string };
|
|
'content:encoded': string;
|
|
'content:encodedSnippet': string;
|
|
};
|
|
|
|
const parser: Parser<CustomFeed, CustomItem> = new Parser({
|
|
customFields: {
|
|
feed: ['foo'],
|
|
item: ['bar'],
|
|
},
|
|
});
|
|
|
|
interface News {
|
|
title?: string;
|
|
url?: string;
|
|
author?: string;
|
|
thumbnail?: string;
|
|
content?: string;
|
|
}
|
|
|
|
interface Podcast {
|
|
title?: string;
|
|
duration?: string;
|
|
created?: Date | string;
|
|
mp3?: string;
|
|
}
|
|
|
|
interface rssPage {
|
|
url: string;
|
|
author: string;
|
|
content: string;
|
|
}
|
|
|
|
export default class UtilsController {
|
|
async getAnitakume(req: Request, res: Response, next: NextFunction) {
|
|
let feed: CustomFeed & Parser.Output<CustomItem>;
|
|
|
|
try {
|
|
feed = await parser.parseURL(urls.BASE_IVOOX);
|
|
} catch (err) {
|
|
return next(err);
|
|
}
|
|
|
|
const podcast: Podcast[] = [];
|
|
const monthNames = [
|
|
'Enero',
|
|
'Febrero',
|
|
'Marzo',
|
|
'Abril',
|
|
'Mayo',
|
|
'Junio',
|
|
'Julio',
|
|
'Agosto',
|
|
'Septiembre',
|
|
'Octubre',
|
|
'Noviembre',
|
|
'Diciembre',
|
|
];
|
|
|
|
feed.items.forEach(item => {
|
|
const date: Date = new Date(item.pubDate!);
|
|
|
|
const formattedObject: Podcast = {
|
|
title: item.title,
|
|
duration: item.itunes.duration,
|
|
created: `${date.getDate()} de ${
|
|
monthNames[date.getMonth()]
|
|
} de ${date.getFullYear()}`,
|
|
mp3: item.enclosure?.url,
|
|
};
|
|
|
|
podcast.push(formattedObject);
|
|
});
|
|
|
|
if (podcast.length > 0) {
|
|
res.status(200).json({ podcast });
|
|
} else {
|
|
res.status(500).json({ message: 'Aruppi lost in the shell' });
|
|
}
|
|
}
|
|
|
|
async getNews(req: Request, res: Response, next: NextFunction) {
|
|
const news: News[] = [];
|
|
const pagesRss: rssPage[] = [
|
|
{ url: urls.BASE_KUDASAI, author: 'Kudasai', content: 'content_encoded' },
|
|
{
|
|
url: urls.BASE_PALOMITRON,
|
|
author: 'Palomitron',
|
|
content: 'description',
|
|
},
|
|
{
|
|
url: urls.BASE_RAMENPARADOS,
|
|
author: 'Ramen para dos',
|
|
content: 'content',
|
|
},
|
|
{
|
|
url: urls.BASE_CRUNCHYROLL,
|
|
author: 'Crunchyroll',
|
|
content: 'content_encoded',
|
|
},
|
|
];
|
|
|
|
try {
|
|
for (const rssPage of pagesRss) {
|
|
const feed = await parser.parseURL(rssPage.url);
|
|
|
|
feed.items.forEach(item => {
|
|
const formattedObject: News = {
|
|
title: item.title,
|
|
url: item.link,
|
|
author: feed.title?.includes('Crunchyroll')
|
|
? 'Crunchyroll'
|
|
: feed.title,
|
|
thumbnail: obtainPreviewNews(item['content:encoded']),
|
|
content: item['content:encoded'],
|
|
};
|
|
|
|
news.push(formattedObject);
|
|
});
|
|
}
|
|
} catch (err) {
|
|
return next(err);
|
|
}
|
|
|
|
res.json({ news });
|
|
}
|
|
|
|
async getImages(req: Request, res: Response, next: NextFunction) {
|
|
const { title } = req.params;
|
|
let data: any;
|
|
|
|
try {
|
|
data = await requestGot(
|
|
`${urls.BASE_QWANT}count=51&q=${title}&t=images&safesearch=1&locale=es_ES&uiv=4`,
|
|
{ scrapy: false, parse: true },
|
|
);
|
|
} catch (err) {
|
|
return next(err);
|
|
}
|
|
|
|
const results: any[] = data.data.result.items.map((item: any) => {
|
|
return {
|
|
type: item.thumb_type,
|
|
thumbnail: `https:${item.thumbnail}`,
|
|
fullsize: `https:${item.media_fullsize}`,
|
|
};
|
|
});
|
|
|
|
if (results.length > 0) {
|
|
res.status(200).json({ images: results });
|
|
} else {
|
|
res.status(500).json({ message: 'Aruppi lost in the shell' });
|
|
}
|
|
}
|
|
|
|
async getVideos(req: Request, res: Response, next: NextFunction) {
|
|
const { channelId } = req.params;
|
|
let data: any;
|
|
|
|
try {
|
|
data = await requestGot(
|
|
`${urls.BASE_YOUTUBE}${channelId}&part=snippet,id&order=date&maxResults=50`,
|
|
{ scrapy: false, parse: true },
|
|
);
|
|
} catch (err) {
|
|
return next(err);
|
|
}
|
|
|
|
const results: any[] = data.items.map((item: any) => {
|
|
return {
|
|
title: item.snippet.title,
|
|
videoId: item.id.videoId,
|
|
thumbDefault: item.snippet.thumbnails.default.url,
|
|
thumbMedium: item.snippet.thumbnails.medium.url,
|
|
thumbHigh: item.snippet.thumbnails.high.url,
|
|
};
|
|
});
|
|
|
|
if (results.length > 0) {
|
|
res.status(200).json({ videos: results });
|
|
} else {
|
|
res.status(500).json({ message: 'Aruppi lost in the shell' });
|
|
}
|
|
}
|
|
|
|
async getSectionVideos(req: Request, res: Response, next: NextFunction) {
|
|
const { type } = req.params;
|
|
let y1: any, y2: any, y3: any;
|
|
let data: any;
|
|
|
|
try {
|
|
if (type === 'learn') {
|
|
data = await requestGot(
|
|
`${urls.BASE_YOUTUBE}UCCyQwSS6m2mVB0-H2FOFJtw&part=snippet,id&order=date&maxResults=50`,
|
|
{ parse: true, scrapy: false },
|
|
);
|
|
} else if (type === 'amv') {
|
|
y1 = await requestGot(
|
|
`${urls.BASE_YOUTUBE}UCkTFkshjAsLMKwhAe1uPC1A&part=snippet,id&order=date&maxResults=25`,
|
|
{ parse: true, scrapy: false },
|
|
);
|
|
|
|
y2 = await requestGot(
|
|
`${urls.BASE_YOUTUBE}UC2cpvlLeowpqnR6bQofwNew&part=snippet,id&order=date&maxResults=25`,
|
|
{ parse: true, scrapy: false },
|
|
);
|
|
} else if (type === 'produccer') {
|
|
y1 = await requestGot(
|
|
`${urls.BASE_YOUTUBE}UC-5MT-BUxTzkPTWMediyV0w&part=snippet,id&order=date&maxResults=25`,
|
|
{ parse: true, scrapy: false },
|
|
);
|
|
|
|
y2 = await requestGot(
|
|
`${urls.BASE_YOUTUBE}UCwUeTOXP3DD9DIvHttowuSA&part=snippet,id&order=date&maxResults=25`,
|
|
{ parse: true, scrapy: false },
|
|
);
|
|
|
|
y3 = await requestGot(
|
|
`${urls.BASE_YOUTUBE}UCA8Vj7nN8bzT3rsukD2ypUg&part=snippet,id&order=date&maxResults=25`,
|
|
{ parse: true, scrapy: false },
|
|
);
|
|
}
|
|
} catch (err) {
|
|
return next(err);
|
|
}
|
|
|
|
if (data && !y1 && !y2 && !y3) {
|
|
const results: any[] = data.items.map((item: any) => ({
|
|
title: item.snippet.title,
|
|
videoId: item.id.videoId,
|
|
thumbDefault: item.snippet.thumbnails.default.url,
|
|
thumbMedium: item.snippet.thumbnails.medium.url,
|
|
thumbHigh: item.snippet.thumbnails.high.url,
|
|
}));
|
|
|
|
res.status(200).json({ videos: results });
|
|
} else if (!data && y1 && y2 && !y3) {
|
|
const results: any[] = y1.items.concat(y2.items).map((item: any) => ({
|
|
title: item.snippet.title,
|
|
videoId: item.id.videoId,
|
|
thumbDefault: item.snippet.thumbnails.default.url,
|
|
thumbMedium: item.snippet.thumbnails.medium.url,
|
|
thumbHigh: item.snippet.thumbnails.high.url,
|
|
}));
|
|
|
|
res.status(200).json({ videos: results });
|
|
} else if (!data && y1 && y2 && y3) {
|
|
const results: any[] = y1.items
|
|
.concat(y2.items.concat(y3.items))
|
|
.map((item: any) => ({
|
|
title: item.snippet.title,
|
|
videoId: item.id.videoId,
|
|
thumbDefault: item.snippet.thumbnails.default.url,
|
|
thumbMedium: item.snippet.thumbnails.medium.url,
|
|
thumbHigh: item.snippet.thumbnails.high.url,
|
|
}));
|
|
|
|
res.status(200).json({ videos: results });
|
|
} else {
|
|
res.status(500).json({ message: 'Aruppi lost in the shell' });
|
|
}
|
|
}
|
|
|
|
async getRadioStations(req: Request, res: Response, next: NextFunction) {
|
|
let data: RadioStation[];
|
|
|
|
try {
|
|
data = await RadioStationModel.find();
|
|
} catch (err) {
|
|
return next(err);
|
|
}
|
|
|
|
const results: any[] = data.map((item: RadioStation) => {
|
|
return {
|
|
name: item.name,
|
|
url: item.url,
|
|
};
|
|
});
|
|
|
|
if (results.length > 0) {
|
|
res.status(200).json({ stations: results });
|
|
} else {
|
|
res.status(500).json({ message: 'Aruppi lost in the shell' });
|
|
}
|
|
}
|
|
|
|
async getAllThemes(req: Request, res: Response, next: NextFunction) {
|
|
let data: Theme[];
|
|
|
|
try {
|
|
data = await ThemeModel.find();
|
|
} catch (err) {
|
|
return next(err);
|
|
}
|
|
|
|
const results: any[] = data.map((item: Theme) => {
|
|
return {
|
|
id: item.id,
|
|
title: item.title,
|
|
year: item.year,
|
|
themes: item.themes,
|
|
};
|
|
});
|
|
|
|
if (results.length > 0) {
|
|
res.status(200).json({ themes: results });
|
|
} else {
|
|
res.status(500).json({ message: 'Aruppi lost in the shell' });
|
|
}
|
|
}
|
|
|
|
async getOpAndEd(req: Request, res: Response, next: NextFunction) {
|
|
const { title } = req.params;
|
|
let themes: any;
|
|
|
|
try {
|
|
themes = await structureThemes(await themeParser.serie(title), true);
|
|
} catch (err) {
|
|
return next(err);
|
|
}
|
|
|
|
if (themes) {
|
|
res.status(200).json({ themes });
|
|
} else {
|
|
res.status(500).json({ message: 'Aruppi lost in the shell' });
|
|
}
|
|
}
|
|
|
|
async getThemesYear(req: Request, res: Response, next: NextFunction) {
|
|
const { year } = req.params;
|
|
let themes: any;
|
|
|
|
try {
|
|
if (year === undefined) {
|
|
themes = await themeParser.allYears();
|
|
} else {
|
|
themes = await structureThemes(await themeParser.year(year), false);
|
|
}
|
|
} catch (err) {
|
|
return next(err);
|
|
}
|
|
|
|
if (themes.length > 0) {
|
|
res.status(200).json({ themes });
|
|
} else {
|
|
res.status(500).json({ message: 'Aruppi lost in the shell' });
|
|
}
|
|
}
|
|
|
|
async randomTheme(req: Request, res: Response, next: NextFunction) {
|
|
let data: any;
|
|
|
|
try {
|
|
data = await requestGot(`${urls.BASE_THEMEMOE}roulette`, {
|
|
parse: true,
|
|
scrapy: false,
|
|
});
|
|
} catch (err) {
|
|
return next(err);
|
|
}
|
|
|
|
const random: any[] = getThemes(data.themes);
|
|
|
|
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' });
|
|
}
|
|
}
|
|
|
|
async getArtist(req: Request, res: Response, next: NextFunction) {
|
|
const { id } = req.params;
|
|
let artists: any;
|
|
|
|
try {
|
|
if (id === undefined) {
|
|
artists = await themeParser.artists();
|
|
} else {
|
|
artists = await structureThemes(await themeParser.artist(id), false);
|
|
}
|
|
} catch (err) {
|
|
return next(err);
|
|
}
|
|
|
|
if (artists.length > 0) {
|
|
res.status(200).json({ artists });
|
|
} else {
|
|
res.status(500).json({ message: 'Aruppi lost in the shell' });
|
|
}
|
|
}
|
|
|
|
async getDestAnimePlatforms(req: Request, res: Response, next: NextFunction) {
|
|
let data: any;
|
|
|
|
try {
|
|
data = await requestGot(
|
|
`${urls.BASE_ARUPPI}res/documents/animelegal/top.json`,
|
|
{ parse: true, scrapy: false },
|
|
);
|
|
} catch (err) {
|
|
return next(err);
|
|
}
|
|
|
|
const destPlatforms: any[] = data.map((item: any) => {
|
|
return {
|
|
id: item.id,
|
|
name: item.name,
|
|
logo: item.logo,
|
|
link: item.link,
|
|
};
|
|
});
|
|
|
|
if (destPlatforms.length > 0) {
|
|
res.status(200).json({ destPlatforms });
|
|
} else {
|
|
res.status(500).json({ message: 'Aruppi lost in the shell' });
|
|
}
|
|
}
|
|
|
|
async getPlatforms(req: Request, res: Response, next: NextFunction) {
|
|
const { id } = req.params;
|
|
let data: any;
|
|
|
|
try {
|
|
if (id === undefined) {
|
|
data = await requestGot(
|
|
`${urls.BASE_ARUPPI}res/documents/animelegal/typeplatforms.json`,
|
|
{ parse: true, scrapy: false },
|
|
);
|
|
} else if (
|
|
id === 'producers' ||
|
|
id === 'apps' ||
|
|
id === 'publishers' ||
|
|
'events'
|
|
) {
|
|
data = await requestGot(
|
|
`${urls.BASE_ARUPPI}res/documents/animelegal/type/${id}.json`,
|
|
{ parse: true, scrapy: false },
|
|
);
|
|
} else {
|
|
data = await requestGot(
|
|
`${urls.BASE_ARUPPI}res/documents/animelegal/type/${id}.json`,
|
|
{ parse: true, scrapy: false },
|
|
);
|
|
}
|
|
} catch (err) {
|
|
return next(err);
|
|
}
|
|
|
|
const platforms: any[] = data.map((item: any) => {
|
|
if (id === undefined) {
|
|
return {
|
|
id: item.id,
|
|
name: item.name,
|
|
comming: item.comming || false,
|
|
cover: item.cover,
|
|
};
|
|
} else if (
|
|
id === 'producers' ||
|
|
id === 'apps' ||
|
|
id === 'publishers' ||
|
|
'events'
|
|
) {
|
|
return {
|
|
id: item.id,
|
|
name: item.name,
|
|
logo: item.logo,
|
|
cover: item.cover,
|
|
description: item.description,
|
|
type: item.type,
|
|
moreInfo: item.moreInfo,
|
|
facebook: item.facebook,
|
|
twitter: item.twitter,
|
|
instagram: item.instagram,
|
|
webInfo: item.webInfo,
|
|
webpage: item.webpage,
|
|
};
|
|
} else {
|
|
return {
|
|
id: item.id,
|
|
name: item.name,
|
|
type: item.type,
|
|
logo: item.logo,
|
|
cover: item.cover,
|
|
webpage: item.webpage,
|
|
};
|
|
}
|
|
});
|
|
|
|
if (platforms.length > 0) {
|
|
res.status(200).json({ platforms });
|
|
} else {
|
|
res.status(500).json({ message: 'Aruppi lost in the shell' });
|
|
}
|
|
}
|
|
}
|