Update to API V2, restoring to ESM and modularizing functions

pull/1/head
carlos-burelo 4 years ago
parent d7755d7f32
commit a44c1bc964

@ -1,6 +0,0 @@
{
"watch": ["src"],
"ext": "ts",
"ignore": ["src/**/.spect.ts"],
"exec": "ts-node src/index.ts"
}

@ -1,33 +1,26 @@
{
"name": "monoschinos-api-ts",
"version": "1.2.0",
"version": "2.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "node dist/index.js",
"build": "tsc ",
"dev": "nodemon"
"start": "node src/index.js",
"dev": "nodemon src/index.js"
},
"type": "module",
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"@types/axios": "^0.14.0",
"@types/cheerio": "^0.22.28",
"@types/cors": "^2.8.10",
"@types/dotenv": "^8.2.0",
"@types/express": "^4.17.11",
"@types/morgan": "^1.9.2",
"nodemon": "^2.0.7",
"ts-node": "^9.1.1",
"typescript": "^4.2.3"
"nodemon": "^2.0.14"
},
"dependencies": {
"axios": "^0.21.1",
"axios": "^0.24.0",
"cheerio": "^1.0.0-rc.5",
"cors": "^2.8.5",
"dotenv": "^8.2.0",
"express": "^4.17.1",
"morgan": "^1.10.0"
"morgan": "^1.10.0",
"node-html-parser": "^5.1.0"
}
}

@ -1,9 +1,8 @@
import express from 'express';
import cors from 'cors';
import morgan from 'morgan';
import routes from './routes/api.routes';
import routes from './routes/api.routes.js';
const app = express();
app.use(cors(), morgan('dev'));
// app.use('/', express.static('docs'));
app.use('/', routes);
export default app;

@ -1,10 +1,6 @@
const appConfig = {
host: process.env.HOST || 'localhost',
port: process.env.PORT || 5000,
};
const page = 'https://monoschinos2.com';
const urls = {
export const urls = {
main: page,
emision: page + '/emision?page=',
search: page + '/search?q=',
@ -15,4 +11,9 @@ const urls = {
ova: page + '/categoria/ova',
};
export { urls, appConfig };
/**
* @returns {string}
*/
export function getAttr(html, selector, attr) {
return html.querySelector(selector).attributes[attr];
}

@ -0,0 +1,67 @@
import cheerio from 'cheerio';
import axios from 'axios';
import { urls } from '../config.js';
export async function getBy(req, res, multiple) {
try {
let { gender, letter, category } = req.params;
let { page } = req.query;
if (!page) {
page = '1';
}
let bodyResponse;
if (multiple) {
bodyResponse = await axios.get(
`${urls.main}/categoria/${category}/genero/${gender}?page=${page}`
);
} else if (gender && !multiple) {
bodyResponse = await axios.get(`${urls.main}/genero/${gender}?page=${page}`);
} else if (letter && !multiple) {
bodyResponse = await axios.get(`${urls.main}/letra/${letter}?page=${page}`);
} else if (category && !multiple) {
bodyResponse = await axios.get(`${urls.main}/categoria/${category}?page=${page}`);
}
const $ = cheerio.load(bodyResponse.data);
const animes = [];
$('.animes .container .row article').each((i, e) => {
let el = $(e);
let id = el.find('.link-anime').attr('href');
id = id.split('/')[4];
let img = el.find('.link-anime .Image img').attr('src');
let title = el.find('.link-anime .Title').text();
let type = el.find('.link-anime .info .category').text();
let year = el.find('.link-anime .info .fecha').text();
let anime = {
id,
img,
title,
type,
year,
};
animes.push(anime);
});
let totalPages = $('.pagination').children().length;
totalPages = $('.pagination').find('.page-item')[totalPages - 2];
let pages = parseInt($(totalPages).text());
res.status(200).json({
animes,
pages,
success: true,
});
} catch (err) {
res.status(500).json({
message: err.message,
success: false,
});
}
}

@ -1,553 +0,0 @@
import cheerio from 'cheerio';
import axios from 'axios';
import { urls } from '../config';
import { SuggestionI, GenderI, AnimeSearchI, EpI } from '../models/interfaces';
import { Request, Response } from 'express';
export async function getAnime(req: Request, res: Response) {
let noImage: string = 'https://monoschinos2.com/assets/img/no_image.png';
let defaulImage: string =
'https://image.freepik.com/free-vector/404-error-page-found_41910-364.jpg';
try {
let { id } = req.params;
const response = await axios.get(`${urls.anime}/${id}`);
const $ = cheerio.load(response.data);
let i = $('.TPost.Serie.Single');
let banner: string = i.find('.Banner img').attr('src');
if (banner == noImage) {
banner = defaulImage;
} else {
banner = banner;
}
let title = i
.find('h1.Title')
.text()
.replace(/Sub Español/gi, '')
.trim();
let sinopsis = i.find('.row .col-sm-9 .Description p').text();
let status = i.find('.row .col-sm-9 .Type').text().trim();
let date = i
.find('.row .col-sm-9 .after-title:nth-child(n)')
.text()
.match(/\d{4}-\d{2}-\d{2}/)[0];
let type = i
.find('.row .col-sm-9 .after-title:nth-child(n)')
.text()
.match(/\|\s\w+/gi)[0]
.replace(/\|?\s?/, '');
let cover = i.find('.Image img').attr('src');
let genders: GenderI[] = [];
i.find('.generos a').each((i, e) => {
let el = $(e);
let title = el.text();
let id = el.attr('href').split('/')[4];
genders.push({ title, id });
});
let episodes: EpI[] = [];
i.find('.container .SerieCaps .item').each((i, e) => {
let el = $(e);
let episodeId = el.attr('href');
episodeId = episodeId.split('/')[4];
episodes.push({
number: parseInt(episodeId.split('-').pop()),
id: episodeId,
});
});
if (!episodes || episodes.length == 0) {
episodes = [];
}
let sugestions: SuggestionI[] = [];
i.find('.container .row .col-12 .recom article').each((i, e) => {
let el = $(e);
let id = el.find('a').attr('href');
id = id.split('/')[4];
let title = el
.find('a .Title')
.text()
.replace(/ Sub Español/gi, '');
let cover = el.find('a .Image img').attr('src');
let year = parseInt(el.find('.fecha').text());
sugestions.push({
id,
title,
cover,
year,
});
});
res.json({
title,
banner,
cover,
sinopsis,
status,
date,
type,
genders,
episodes,
sugestions,
});
} catch (err) {
res.json({
message: err.message,
success: false,
});
}
}
export async function getAnimes(req: Request, res: Response) {
try {
let { page } = req.params;
!page ? (page = '1') : (page = page);
const bodyResponse = await axios.get(`${urls.main}/animes?page=${page}`);
const $ = cheerio.load(bodyResponse.data);
const animes = [];
$('.animes .container .row article').each((i, e) => {
let el = $(e);
let id = el.find('a').attr('href');
id = id.split('/')[4];
let title = el.find('.Title').text();
let img = el.find('.Image img').attr('src');
let category = el.find('.category').text();
category = category.substring(1, category.length);
let year = parseInt(el.find('.fecha').text());
const anime = {
id,
title,
img,
category,
year,
};
animes.push(anime);
});
let totalPages: any = $('.pagination').children().length;
totalPages = $('.pagination').find('.page-item')[totalPages - 2];
let pages = parseInt($(totalPages).text());
let current = parseInt(page);
res.status(200).json({
current,
pages,
animes,
});
} catch (err) {
res.status(500).json({
message: err.message,
success: false,
});
}
}
export async function searchAnime(req: Request, res: Response) {
try {
let { id } = req.params;
const response = await axios.get(`${urls.search}${id}`);
const $ = cheerio.load(response.data);
let animes = [];
$('.animes .row article').each((i, e) => {
let el = $(e);
let title = el.find('h3.Title').text();
let cover = el.find('div.Image .cover .img-fluid').attr('src');
let id1 = el.find('a.link-anime').attr('href');
let id = id1.split('/')[4];
let category = el.find('.category').text();
category = category.substring(1, category.length);
let year = parseInt(el.find('.fecha').text());
let anime: AnimeSearchI = {
id,
title,
cover,
category,
year,
};
animes.push(anime);
});
res.json(animes);
} catch (err) {
res.json({
message: err.message,
success: false,
});
}
}
export async function getEpisode(req: Request, res: Response) {
try {
let { id } = req.params;
const response = await axios.get(`${urls.episode}/${id}`);
const $ = cheerio.load(response.data);
let epnum = $('.Episode .Title-epi').text();
let title = $('.Episode .Title-epi').text().replace('Sub Español', '').trim();
let number: any = epnum.split(' ');
number = parseInt(number[number.length - 3]);
let ctrls = {
prev: false,
next: false,
};
$('.d-flex.justify-content-center.mb-4').map((i, e) => {
let el = $(e);
if (el.text().includes('Anterior')) {
ctrls.prev = true;
}
if (el.text().includes('Siguiente')) {
ctrls.next = true;
}
});
let animeId = $('a.btnWeb.green.Current')
.attr('href')
.replace('https://monoschinos2.com/anime/', '');
let videos = [];
let videosContainer = $('.Episode .content .row .TPlayer').text();
$(videosContainer).each((i, e) => {
let el = $(e);
let url = el.attr('src');
if (url) {
url = url.split('url=')[1];
url = decodeURIComponent(url);
url = url.split('&id')[0];
let videolinks = new URL(url);
let { host } = videolinks;
let name = host.replace(/\.com|www\.|\.ru|repro\.|\.co|\.nz/, '');
name = `${name.slice(0, 1).toUpperCase()}${name.slice(1)}`;
let servers = {
url,
name,
};
videos.push(servers);
}
});
let downloads = [];
let downloadsContainer = $('#downloads table tbody tr');
$(downloadsContainer).each((i, e) => {
let el = $(e);
let link = el.find('a').attr('href');
let sn = link.replace(/\.com|www\.|\.ru|repro\.|\.co|\.nz/, '');
let servername = sn.slice(8);
let svn = servername.indexOf('/');
let server = servername.slice(0, svn);
server = `${server.slice(0, 1).toUpperCase()}${server.slice(1)}`;
let down = {
server,
link,
};
if (down) {
downloads.push(down);
}
});
res.json({
title,
animeId,
ctrls,
number,
videos,
downloads,
});
} catch (err) {
res.status(500).json({
message: err.message,
success: false,
});
}
}
export async function getCategories(req: Request, res: Response) {
try {
const response = await axios.get(`${urls.main}/animes`);
const $ = cheerio.load(response.data);
let categories = [];
let categoriesContainer = $('.filter-container .clearfix .float-left')[0];
$(categoriesContainer)
.find('.dropdown-menu .dropdown-item')
.each((i, e) => {
let el = $(e);
let title = el.text();
let id = el.attr('href');
id = id.split('/')[2];
let category = {
title,
id,
};
categories.push(category);
});
res.status(200).json(categories);
} catch (err) {
res.status(500).json({
message: err.message,
success: false,
});
}
}
export async function getGenders(req: Request, res: Response) {
try {
const response = await axios.get(`${urls.main}/animes`);
const $ = cheerio.load(response.data);
let genders = [];
let gendersContainer = $('.filter-container .clearfix .float-left')[1];
$(gendersContainer)
.find('.dropdown-menu .dropdown-item')
.each((i, e) => {
let el = $(e);
let title = el.text();
if (title.charAt(0) == ' ') {
title = title.substring(1, title.length);
}
let id = el.attr('href');
id = id.split('/')[2];
let gender: GenderI = {
title,
id,
};
genders.push(gender);
});
res.json(genders);
} catch (err) {
res.status(500).json({
message: err,
success: false,
});
}
}
export async function getGender(req: any, res: any) {
try {
let { gender } = req.params;
let { page } = req.params;
!page ? (page = 1) : (page = page);
const bodyResponse = await axios.get(`${urls.main}/genero/${gender}?page=${page}`);
const $ = cheerio.load(bodyResponse.data);
const animes = [];
$('.animes .container .row article').each((i, e) => {
let el = $(e);
let id = el.find('a').attr('href');
id = id.split('/')[4];
let title = el.find('.Title').text();
let img = el.find('.Image img').attr('src');
let category = el.find('.category').text();
category = category.substring(1, category.length);
let year = parseInt(el.find('.fecha').text());
const anime = {
id,
title,
img,
category,
year,
};
animes.push(anime);
});
let totalPages: any = $('.pagination').children().length;
totalPages = $('.pagination').find('.page-item')[totalPages - 2];
let pages = parseInt($(totalPages).text());
let current = parseInt(page);
res.status(200).json({
current,
pages,
animes,
});
} catch (err) {
res.status(500).json({
message: err.message,
success: false,
});
}
}
export async function getYears(req: Request, res: Response) {
try {
const response = await axios.get(`${urls.main}/animes`);
const $ = cheerio.load(response.data);
let years = [];
let YearsContainer = $('.filter-container .clearfix .float-left')[2];
$(YearsContainer)
.find('.dropdown-menu .dropdown-item')
.each((i, e) => {
let el = $(e);
let title = el.text();
if (title.charAt(0) == ' ') {
title = title.substring(1, title.length);
}
let id = el.attr('href');
id = id.split('/')[2];
let year: GenderI = {
title,
id,
};
years.push(year);
});
res.json(years);
} catch (err) {
res.status(500).json({
message: err,
success: false,
});
}
}
export async function getYear(req: Request, res: Response) {
try {
let { year } = req.params;
let { page } = req.params;
!page ? (page = '1') : (page = page);
const bodyResponse = await axios.get(`${urls.main}/year/${year}?page=${page}`);
const $ = cheerio.load(bodyResponse.data);
const animes = [];
$('.animes .container .row article').each((i, e) => {
let el = $(e);
let id = el.find('a').attr('href');
id = id.split('/')[4];
let title = el.find('.Title').text();
let img = el.find('.Image img').attr('src');
let category = el.find('.category').text();
category = category.substring(1, category.length);
let year = parseInt(el.find('.fecha').text());
const anime = {
id,
title,
img,
category,
year,
};
animes.push(anime);
});
let totalPages: any = $('.pagination').children().length;
totalPages = $('.pagination').find('.page-item')[totalPages - 2];
let pages = parseInt($(totalPages).text());
let current = parseInt(page);
res.status(200).json({
current,
pages,
animes,
});
} catch (err) {
res.status(500).json({
message: err.message,
success: false,
});
}
}
export async function getLetters(req: Request, res: Response) {
try {
const bodyResponse = await axios.get(`${urls.main}/animes`);
const $ = cheerio.load(bodyResponse.data);
const letters = [];
let lettersContainer = $('.filter-container .clearfix .float-left')[3];
$(lettersContainer)
.find('.dropdown-menu .dropdown-item')
.each((i, e) => {
let el = $(e);
let title = el.text();
let id = el.attr('href');
id = id.split('/')[2];
let letter = {
title,
id,
};
letters.push(letter);
});
res.status(200).json(letters);
} catch (err) {
res.status(500).json({
message: err.message,
success: false,
});
}
}
export async function getBy(req: Request, res: Response, multiple?) {
try {
let { gender, letter, category } = req.params;
let { page } = req.query;
if (!page) {
page = '1';
}
let bodyResponse;
if (multiple) {
bodyResponse = await axios.get(
`${urls.main}/categoria/${category}/genero/${gender}?page=${page}`
);
} else if (gender && !multiple) {
bodyResponse = await axios.get(`${urls.main}/genero/${gender}?page=${page}`);
} else if (letter && !multiple) {
bodyResponse = await axios.get(`${urls.main}/letra/${letter}?page=${page}`);
} else if (category && !multiple) {
bodyResponse = await axios.get(`${urls.main}/categoria/${category}?page=${page}`);
}
const $ = cheerio.load(bodyResponse.data);
const animes = [];
$('.animes .container .row article').each((i, e) => {
let el = $(e);
let id = el.find('.link-anime').attr('href');
id = id.split('/')[4];
let img = el.find('.link-anime .Image img').attr('src');
let title = el.find('.link-anime .Title').text();
let type = el.find('.link-anime .info .category').text();
let year = el.find('.link-anime .info .fecha').text();
let anime = {
id,
img,
title,
type,
year,
};
animes.push(anime);
});
let totalPages: any = $('.pagination').children().length;
totalPages = $('.pagination').find('.page-item')[totalPages - 2];
let pages = parseInt($(totalPages).text());
res.status(200).json({
animes,
pages,
success: true,
});
} catch (err) {
res.status(500).json({
message: err.message,
success: false,
});
}
}
// export {
// getAnime,
// getAnimes,
// searchAnime,
// getEpisode,
// getCategories,
// getGenders,
// getGender,
// getYears,
// getYear,
// getLetters,
// getBy
// };

@ -0,0 +1,53 @@
import axios from 'axios';
import { getAttr, urls } from '../config.js';
import { parse } from 'node-html-parser';
export async function getAnime(req, res) {
try {
const url = 'https://monoschinos2.com/';
const noImage = 'https://monoschinos2.com/assets/img/no_image.png';
const defaulImage = 'https://image.freepik.com/free-vector/404-error-page-found_41910-364.jpg';
const { id } = req.params;
const { data } = await axios.get(`${urls.anime}/${id}`);
const html = parse(data);
const image = getAttr(html, '.Banner img', 'src');
res.status(200).json({
banner: image == noImage ? defaulImage : image || null,
image: getAttr(html, 'figure img.img-fluid', 'src') || null,
title:
html
.querySelector('h1.Title')
.text.replace(/Sub Español/gi, '')
.trim() || null,
sinopsis: html.querySelector('.row .col-sm-9 .Description p').text || null,
status: html.querySelector('.row .col-sm-9 .Type').text.trim() || null,
date: html.querySelector('.after-title.mb-2').text.match(/\d+-\d+-\d+/)[0] || null,
type:
html.querySelector('.after-title.mb-2').text.match(/(\d+-\d+-\d+)\s?\|\s([A-Za-z]+)/)[2] ||
null,
genders: html.querySelectorAll('.generos a').map((g) => g.text) || null,
episodes:
html.querySelectorAll('.SerieCaps a').map((cap) => {
const epId = cap.attributes['href'].replace(`${url}ver/`, '');
return {
no: parseInt(epId.split('-').pop()),
id: epId,
};
}) || null,
sugestions:
html.querySelectorAll('.recom article').map((i) => {
return {
id: getAttr(i, 'a', 'href').replace(`${url}anime/`, ''),
image: getAttr(i, 'a .Image img', 'src'),
title: i.querySelector('a .Title').text,
year: parseInt(i.querySelector('.fecha').text),
};
}) || null,
});
} catch (error) {
res.status(500).json({
id: 'intertal-server-error',
message: error.message,
});
}
}

@ -0,0 +1,27 @@
import { parse } from 'node-html-parser';
import axios from 'axios';
import { getAttr, urls } from '../config.js';
export async function getAnimes(req, res) {
try {
let { page = '1' } = req.params;
const { data } = await axios.get(`${urls.main}/animes?page=${page}`);
const html = parse(data);
res.json(
html.querySelectorAll('.animes .container .row article').map((i) => {
const id = getAttr(i, 'a', 'href');
return {
id: id.split('/').pop() || null,
title: i.querySelector('.Title').text || null,
image: getAttr(i, '.Image img', 'src') || null,
type: i.querySelector('.category.text-uppercase').text || null,
year: parseInt(i.querySelector('.fecha').text) || null,
};
})
);
} catch (err) {
res.status(500).json({
message: err.message,
});
}
}

@ -0,0 +1,35 @@
import axios from 'axios';
import { parse } from 'node-html-parser';
import { urls, getAttr } from '../config.js';
export async function getBy(req, res) {
try {
const { gender, category, letter, year, page = '1', sort, order } = req.query;
let response;
if (gender) response = await axios.get(`${urls.main}/genero/${gender}?page=${page}`);
if (category) response = await axios.get(`${urls.main}/categoria/${category}?page=${page}`);
if (letter) response = await axios.get(`${urls.main}/letra/${letter}?page=${page}`);
if (year) response = await axios.get(`${urls.main}/year/${year}?page=${page}`);
const { data } = response;
const html = parse(data);
const animes = html.querySelectorAll('.animes .container .row article').map((i) => {
const id = getAttr(i, 'a', 'href');
return {
id: id.split('/').pop() || null,
title: i.querySelector('.Title').text.trim() || null,
image: getAttr(i, '.Image img', 'src') || null,
type: i.querySelector('.category.text-uppercase').text.trim() || null,
year: parseInt(i.querySelector('.fecha').text) || null,
};
});
const isAsc = order == 'asc';
const ordered = animes.sort((a, b) => {
return (a[sort] < b[sort] ? -1 : 1) * (isAsc ? 1 : -1);
});
res.status(200).json(sort ? ordered : animes);
} catch (err) {
res.status(500).json({
message: err.message,
});
}
}

@ -0,0 +1,25 @@
import axios from 'axios';
import { parse } from 'node-html-parser';
import { urls } from '../config.js';
export async function getCategories(req, res) {
try {
const { data } = await axios.get(`${urls.main}/animes`);
const html = parse(data);
res.status(200).json(
html
.querySelectorAll('div[aria-labelledby="categoryMenuButton"] a')
.map((i) => {
return {
name: i.text.trim(),
id: i?.attributes['href'].replace('/categoria/', ''),
};
})
.filter((i) => i.id !== '')
);
} catch (err) {
res.status(500).json({
message: err.message,
});
}
}

@ -0,0 +1,26 @@
import axios from 'axios';
import { parse } from 'node-html-parser';
import { getAttr, urls } from '../config.js';
export async function getEmision(req, res) {
try {
let { page = '1' } = req.query;
const { data } = await axios.get(`${urls.emision}${page}`);
const html = parse(data);
res.status(200).json(
html.querySelectorAll('.animes .container .row article').map((i) => {
return {
id: getAttr(i, 'a', 'href').split('/').pop(),
title: i.querySelector('.Title').text.trim(),
image: getAttr(i, '.Image img', 'src'),
type: i.querySelector('.category').text.trim(),
year: parseInt(i.querySelector('.fecha').text),
};
})
);
} catch (err) {
res.status(500).json({
message: err.message,
});
}
}

@ -1,34 +0,0 @@
import axios from 'axios';
import cheerio from 'cheerio';
import { Request, Response } from 'express';
import { urls } from '../config';
export async function getEmision(req: Request, res: Response) {
try {
let { page = '1' } = req.query;
const { data } = await axios.get(`${urls.emision}${page}`);
const $ = cheerio.load(data);
const animes = $('.animes .container .row article')
.map((i, e) => {
let el: cheerio.Cheerio = $(e);
let category: string = el.find('.category').text();
return {
id: el.find('a').attr('href').split('/')[4],
title: el.find('.Title').text(),
img: el.find('.Image img').attr('src'),
category: el.find('.category').text().substring(1, category.length),
year: parseInt(el.find('.fecha').text()),
};
})
.toArray();
let pagesBase: string = $('.pagination').text().match(/\d/g).pop();
let pages = parseInt(pagesBase);
res.json({ animes, pages }).status(200);
} catch (err) {
res.json({
message: err.message,
success: false,
});
}
}
// 46 lines before refactoring

@ -0,0 +1,48 @@
import axios from 'axios';
import { getAttr, urls } from '../config.js';
import { parse } from 'node-html-parser';
export async function getEpisode(req, res) {
try {
const { id } = req.params;
const { data } = await axios.get(`${urls.episode}/${id}`);
const html = parse(data);
const map = {
Anterior: true,
Siguiente: true,
};
const videos = html.querySelectorAll('.TPlayer.mt-3.mb-3 .TPlayerTb').map((i) => {
const tag = parse(i.text);
return tag.querySelector('iframe')?.attributes['src'];
});
const servers = html.querySelectorAll('#downloads table tbody tr').map((i) => {
return {
name: getAttr(i, 'a', 'href').match(/\/\/(.+)\//)[1],
url: getAttr(i, 'a', 'href'),
};
});
const ctrls = {};
html.querySelectorAll('.d-flex.justify-content-center.mb-4 a').forEach((i) => {
const id = i.text.replace(/\s/g, '');
let key;
id == 'Siguiente' ? (key = 'next') : id == 'Anterior' ? (key = 'prev') : 'menu';
ctrls[key] = map[id];
});
delete ctrls['menu'];
res.json({
title: html.querySelector('.Title-epi').text,
no: parseInt(id.split('-').pop()) || 0,
animeId: getAttr(html, 'a.btnWeb.green.Current', 'href').replace(
'https://monoschinos2.com/anime/',
''
),
videos: videos.filter((i) => i !== undefined),
servers,
ctrls,
});
} catch (err) {
res.status(500).json({
message: err.message,
});
}
}

@ -0,0 +1,26 @@
import axios from 'axios';
import { parse } from 'node-html-parser';
import { urls } from '../config.js';
export async function getGenders(req, res) {
try {
const { data } = await axios.get(`${urls.main}/animes`);
const html = parse(data);
res.status(200).json(
html
.querySelectorAll('div[aria-labelledby="genreMenuButton"] a')
.map((i) => {
return {
name: i.text.trim(),
id: i?.attributes['href'].replace('/genero/', ''),
};
})
.filter((i) => i.id !== '')
);
} catch (err) {
res.status(500).json({
message: err,
success: false,
});
}
}

@ -0,0 +1,24 @@
import axios from 'axios';
import { getAttr, urls } from '../config.js';
import { parse } from 'node-html-parser';
export async function getLastest(req, res) {
try {
const { data } = await axios.get(urls.main);
const html = parse(data);
res.json(
html.querySelectorAll('.row article').map((i) => {
const id = getAttr(i, 'a', 'href').split('/').pop();
return {
id: id || null,
title: i.querySelector('.Title').text || null,
image: getAttr(i, '.Image img', 'src') || null,
type: i.querySelector('.Image figure span').text.trim() || null,
episode: parseInt(id.split('-').pop()) || null,
};
})
);
} catch (error) {
return res.json({ error: error.message }).status(500);
}
}

@ -1,32 +0,0 @@
import cheerio from 'cheerio';
import axios from 'axios';
import { urls } from '../config';
import { Response, Request } from 'express';
export async function getLastest(req: Request, res: Response) {
try {
const { data } = await axios.get(urls.main);
const $ = cheerio.load(data);
let getLastest = $('.container .caps .container')[0];
const animes: cheerio.Element[] = $(getLastest)
.find('.row article')
.map((i, e) => {
let el: cheerio.Cheerio = $(e);
let type: string = el.find('.Image figure span').text();
return {
id: el
.find('a')
.attr('href')
.replace(/https:\/\/monoschinos2\.com\/ver\//, ''),
title: el.find('.Title').html().split('\t')[0],
cover: el.find('.Image img').attr('src'),
type: type.substring(1, type.length),
episode: parseInt(el.find('.dataEpi .episode').text().split('\n')[1]),
};
})
.toArray();
return res.json(animes).status(200);
} catch (error) {
return res.json({ error: error.message }).status(500);
}
}

@ -0,0 +1,26 @@
import axios from 'axios';
import { parse } from 'node-html-parser';
import { urls } from '../config.js';
export async function getYears(req, res) {
try {
const { data } = await axios.get(`${urls.main}/animes`);
const html = parse(data);
res.status(200).json(
html
.querySelectorAll('div[aria-labelledby="yearMenuButton"] a')
.map((i) => {
return {
name: i.text.trim(),
id: i?.attributes['href'].replace('/year/', ''),
};
})
.filter((i) => i.id !== '')
);
} catch (err) {
res.status(500).json({
message: err,
success: false,
});
}
}

@ -0,0 +1,10 @@
export * from './getLastest.js';
export * from './getEmision.js';
export * from './getAnime.js';
export * from './searchAnimes.js';
export * from './getAnimes.js';
export * from './getEpisode.js';
export * from './getCategories.js';
export * from './getGenders.js';
export * from './getYears.js';
export * from './getBy.js';

@ -1,2 +0,0 @@
export * from './getLastest';
export * from './getEmision';

@ -0,0 +1,27 @@
import { parse } from 'node-html-parser';
import axios from 'axios';
import { getAttr, urls } from '../config.js';
export async function searchAnime(req, res) {
try {
let { id } = req.params;
const { data } = await axios.get(`${urls.search}${id}`);
const html = parse(data);
res.json(
html.querySelectorAll('.animes .row article').map((i) => {
return {
id: getAttr(i, 'a', 'href').split('/').pop() || null,
title: i.querySelector('h3.Title').text || null,
image: getAttr(i, '.cover .img-fluid', 'src') || null,
type: i.querySelector('.category.text-uppercase').text.trim() || null,
year: parseInt(i.querySelector('.fecha').text) || null,
};
})
);
} catch (error) {
res.status(500).json({
id: 'intertal-server-error',
message: error.message,
});
}
}

@ -0,0 +1,6 @@
import app from './app.js';
app.listen(process.env.PORT || 5000, () => {
console.clear();
console.info(`API Running on: 5000 ============================`);
});

@ -1,11 +0,0 @@
import app from './app';
import { appConfig } from './config'
function init(host:any, port:any) {
app.listen(port, host, ( ) => {
console.clear()
console.info(`API Running on: ${host}:${port} ============================`);
})
}
init(appConfig.host, appConfig.port)

@ -1,79 +0,0 @@
export interface EmisionResponse{
animes: Array<EmisionI>;
pages: number;
}
export interface EmisionI{
id: string;
title: string;
img: string;
category: string;
year: number;
}
// const anime: {
// }
export interface LastestAnimeI {
title: string
cover: string
id?: string
episode: string
type: string
}
export interface AnimeI{
id: string;
title: string;
banner: string;
type: string;
cover: string;
sinopsis: string;
status: string;
date: string;
genders: GenderI[];
sugestions: SuggestionI[];
episodes: EpI[];
}
export interface GenderI{
id:string;
title:string;
}
export interface SuggestionI{
id:string;
title:string;
cover:string;
year:number;
}
export interface EpI{
id:string;
number:number;
}
export interface AnimeSearchI {
id?: string;
title: string;
cover: string
category: string;
year: number;
}
export interface EpisodeI {
id?: string;
title: string;
number: string
videos: Array<VideosI>;
downloads: Array<DownloadsI>;
}
export interface VideosI {
url: string;
title: string;
}
export interface DownloadsI {
url: string;
server: string;
}

@ -1,20 +1,24 @@
import { Router } from 'express';
const routes = Router();
import {
getEmision,
getGenders,
getLastest,
getAnime,
getAnimes,
searchAnime,
getAnimes,
getEpisode,
getGenders,
getGender,
getCategories,
getYears,
getYear,
getLetters,
getBy,
} from '../controllers/controller';
} from '../controllers/index.js';
import { getEmision, getLastest } from '../controllers';
routes.get('/', (_, res) => {
res.json({
message: 'API Works',
});
});
routes.get('/lastest', (req, res) => {
getLastest(req, res);
@ -37,33 +41,33 @@ routes.get('/search/:id', (req, res) => {
routes.get('/genders', (req, res) => {
getGenders(req, res);
});
routes.get('/gender/:gender/:page', (req, res) => {
getGender(req, res);
});
routes.get('/categories', (req, res) => {
getCategories(req, res);
});
routes.get('/years', (req, res) => {
getYears(req, res);
});
routes.get('/year/:year/:page', (req, res) => {
getYear(req, res);
});
routes.get('/letters', (req, res) => {
getLetters(req, res);
});
routes.get('/category/:category/gender/:gender', (req, res) => {
getBy(req, res, true);
});
routes.get('/gender/:gender', (req, res) => {
getBy(req, res);
});
routes.get('/letter/:letter', (req, res) => {
routes.get('/by', (req, res) => {
getBy(req, res);
});
// routes.get('/category/:category/gender/:gender', (req, res) => {
// getBy(req, res, true);
// });
// routes.get('/gender/:gender', (req, res) => {
// getBy(req, res);
// });
routes.get('/category/:category', (req, res) => {
getBy(req, res);
});
// routes.get('/letter/:letter', (req, res) => {
// getBy(req, res);
// });
// routes.get('/category/:category', (req, res) => {
// getBy(req, res);
// });
export default routes;

@ -1,71 +0,0 @@
{
"compilerOptions": {
/* Visit https://aka.ms/tsconfig.json to read more about this file */
/* Basic Options */
// "incremental": true, /* Enable incremental compilation */
"target": "ES2020", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */
"module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */
// "lib": [], /* Specify library files to be included in the compilation. */
// "allowJs": true, /* Allow javascript files to be compiled. */
// "checkJs": true, /* Report errors in .js files. */
// "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', 'react', 'react-jsx' or 'react-jsxdev'. */
// "declaration": true, /* Generates corresponding '.d.ts' file. */
// "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */
// "sourceMap": true, /* Generates corresponding '.map' file. */
// "outFile": "./", /* Concatenate and emit output to single file. */
"outDir": "./dist/", /* Redirect output structure to the directory. */
"rootDir": "./src/", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
// "composite": true, /* Enable project compilation */
// "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */
"removeComments": true, /* Do not emit comments to output. */
// "noEmit": true, /* Do not emit outputs. */
// "importHelpers": true, /* Import emit helpers from 'tslib'. */
// "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
// "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
/* Strict Type-Checking Options */
"strict": false, /* Enable all strict type-checking options. */
// "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
"strictNullChecks": false, /* Enable strict null checks. */
// "strictFunctionTypes": true, /* Enable strict checking of function types. */
// "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */
// "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */
// "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
// "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
/* Additional Checks */
// "noUnusedLocals": true, /* Report errors on unused locals. */
// "noUnusedParameters": true, /* Report errors on unused parameters. */
// "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
// "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
// "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */
// "noPropertyAccessFromIndexSignature": true, /* Require undeclared properties from index signatures to use element accesses. */
/* Module Resolution Options */
"moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
// "baseUrl": "./", /* Base directory to resolve non-absolute module names. */
// "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
// "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */
// "typeRoots": [], /* List of folders to include type definitions from. */
// "types": [], /* Type declaration files to be included in compilation. */
// "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
"esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
// "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
/* Source Map Options */
// "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */
// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
// "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */
// "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */
/* Experimental Options */
// "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */
// "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */
/* Advanced Options */
"skipLibCheck": true, /* Skip type checking of declaration files. */
"forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */
}
}

@ -14,101 +14,6 @@
dependencies:
defer-to-connect "^1.0.1"
"@types/axios@^0.14.0":
version "0.14.0"
resolved "https://registry.yarnpkg.com/@types/axios/-/axios-0.14.0.tgz#ec2300fbe7d7dddd7eb9d3abf87999964cafce46"
integrity sha1-7CMA++fX3d1+udOr+HmZlkyvzkY=
dependencies:
axios "*"
"@types/body-parser@*":
version "1.19.1"
resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.19.1.tgz#0c0174c42a7d017b818303d4b5d969cb0b75929c"
integrity sha512-a6bTJ21vFOGIkwM0kzh9Yr89ziVxq4vYH2fQ6N8AeipEzai/cFK6aGMArIkUeIdRIgpwQa+2bXiLuUJCpSf2Cg==
dependencies:
"@types/connect" "*"
"@types/node" "*"
"@types/cheerio@^0.22.28":
version "0.22.30"
resolved "https://registry.yarnpkg.com/@types/cheerio/-/cheerio-0.22.30.tgz#6c1ded70d20d890337f0f5144be2c5e9ce0936e6"
integrity sha512-t7ZVArWZlq3dFa9Yt33qFBQIK4CQd1Q3UJp0V+UhP6vgLWLM6Qug7vZuRSGXg45zXeB1Fm5X2vmBkEX58LV2Tw==
dependencies:
"@types/node" "*"
"@types/connect@*":
version "3.4.35"
resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.35.tgz#5fcf6ae445e4021d1fc2219a4873cc73a3bb2ad1"
integrity sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==
dependencies:
"@types/node" "*"
"@types/cors@^2.8.10":
version "2.8.12"
resolved "https://registry.yarnpkg.com/@types/cors/-/cors-2.8.12.tgz#6b2c510a7ad7039e98e7b8d3d6598f4359e5c080"
integrity sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw==
"@types/dotenv@^8.2.0":
version "8.2.0"
resolved "https://registry.yarnpkg.com/@types/dotenv/-/dotenv-8.2.0.tgz#5cd64710c3c98e82d9d15844375a33bf1b45d053"
integrity sha512-ylSC9GhfRH7m1EUXBXofhgx4lUWmFeQDINW5oLuS+gxWdfUeW4zJdeVTYVkexEW+e2VUvlZR2kGnGGipAWR7kw==
dependencies:
dotenv "*"
"@types/express-serve-static-core@^4.17.18":
version "4.17.24"
resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.24.tgz#ea41f93bf7e0d59cd5a76665068ed6aab6815c07"
integrity sha512-3UJuW+Qxhzwjq3xhwXm2onQcFHn76frIYVbTu+kn24LFxI+dEhdfISDFovPB8VpEgW8oQCTpRuCe+0zJxB7NEA==
dependencies:
"@types/node" "*"
"@types/qs" "*"
"@types/range-parser" "*"
"@types/express@^4.17.11":
version "4.17.13"
resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.13.tgz#a76e2995728999bab51a33fabce1d705a3709034"
integrity sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA==
dependencies:
"@types/body-parser" "*"
"@types/express-serve-static-core" "^4.17.18"
"@types/qs" "*"
"@types/serve-static" "*"
"@types/mime@^1":
version "1.3.2"
resolved "https://registry.yarnpkg.com/@types/mime/-/mime-1.3.2.tgz#93e25bf9ee75fe0fd80b594bc4feb0e862111b5a"
integrity sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==
"@types/morgan@^1.9.2":
version "1.9.3"
resolved "https://registry.yarnpkg.com/@types/morgan/-/morgan-1.9.3.tgz#ae04180dff02c437312bc0cfb1e2960086b2f540"
integrity sha512-BiLcfVqGBZCyNCnCH3F4o2GmDLrpy0HeBVnNlyZG4fo88ZiE9SoiBe3C+2ezuwbjlEyT+PDZ17//TAlRxAn75Q==
dependencies:
"@types/node" "*"
"@types/node@*":
version "16.10.1"
resolved "https://registry.yarnpkg.com/@types/node/-/node-16.10.1.tgz#f3647623199ca920960006b3dccf633ea905f243"
integrity sha512-4/Z9DMPKFexZj/Gn3LylFgamNKHm4K3QDi0gz9B26Uk0c8izYf97B5fxfpspMNkWlFupblKM/nV8+NA9Ffvr+w==
"@types/qs@*":
version "6.9.7"
resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.7.tgz#63bb7d067db107cc1e457c303bc25d511febf6cb"
integrity sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==
"@types/range-parser@*":
version "1.2.4"
resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.4.tgz#cd667bcfdd025213aafb7ca5915a932590acdcdc"
integrity sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==
"@types/serve-static@*":
version "1.13.10"
resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.13.10.tgz#f5e0ce8797d2d7cc5ebeda48a52c96c4fa47a8d9"
integrity sha512-nCkHGI4w7ZgAdNkrEu0bv+4xNV/XDqW+DydknebMOQwkpDGx8G+HTlj7R7ABI8i8nKxVw0wtKPi1D+lPOkh4YQ==
dependencies:
"@types/mime" "^1"
"@types/node" "*"
abbrev@1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8"
@ -149,22 +54,17 @@ anymatch@~3.1.2:
normalize-path "^3.0.0"
picomatch "^2.0.4"
arg@^4.1.0:
version "4.1.3"
resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089"
integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==
array-flatten@1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2"
integrity sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=
axios@*, axios@^0.21.1:
version "0.21.4"
resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.4.tgz#c67b90dc0568e5c1cf2b0b858c43ba28e2eda575"
integrity sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==
axios@^0.24.0:
version "0.24.0"
resolved "https://registry.yarnpkg.com/axios/-/axios-0.24.0.tgz#804e6fa1e4b9c5288501dd9dff56a7a0940d20d6"
integrity sha512-Q6cWsys88HoPgAaFAVUb0WpPk0O8iTeisR9IMqy9G8AbO4NlpVknrnQS03zzF9PGAWgO3cgletO3VjV/P7VztA==
dependencies:
follow-redirects "^1.14.0"
follow-redirects "^1.14.4"
balanced-match@^1.0.0:
version "1.0.2"
@ -233,11 +133,6 @@ braces@~3.0.2:
dependencies:
fill-range "^7.0.1"
buffer-from@^1.0.0:
version "1.1.2"
resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5"
integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==
bytes@3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6"
@ -384,11 +279,6 @@ cors@^2.8.5:
object-assign "^4"
vary "^1"
create-require@^1.1.0:
version "1.1.1"
resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333"
integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==
crypto-random-string@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-2.0.0.tgz#ef2a7a966ec11083388369baa02ebead229b30d5"
@ -456,11 +346,6 @@ destroy@~1.0.4:
resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80"
integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=
diff@^4.0.1:
version "4.0.2"
resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d"
integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==
dom-serializer@^1.0.1, dom-serializer@^1.3.2:
version "1.3.2"
resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-1.3.2.tgz#6206437d32ceefaec7161803230c7a20bc1b4d91"
@ -498,11 +383,6 @@ dot-prop@^5.2.0:
dependencies:
is-obj "^2.0.0"
dotenv@*:
version "10.0.0"
resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-10.0.0.tgz#3d4227b8fb95f81096cdd2b66653fb2c7085ba81"
integrity sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==
dotenv@^8.2.0:
version "8.6.0"
resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-8.6.0.tgz#061af664d19f7f4d8fc6e4ff9b584ce237adcb8b"
@ -611,10 +491,10 @@ finalhandler@~1.1.2:
statuses "~1.5.0"
unpipe "~1.0.0"
follow-redirects@^1.14.0:
version "1.14.4"
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.4.tgz#838fdf48a8bbdd79e52ee51fb1c94e3ed98b9379"
integrity sha512-zwGkiSXC1MUJG/qmeIFH2HBJx9u0V46QGUe3YR1fXG8bXQxq7fLj0RjLZQ5nubr9qNJUZrH+xUcwXEoXNpfS+g==
follow-redirects@^1.14.4:
version "1.14.5"
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.5.tgz#f09a5848981d3c772b5392309778523f8d85c381"
integrity sha512-wtphSXy7d4/OR+MvIFbCVBDzZ5520qV8XfPklSN5QtxuMUJZ+b0Wnst1e1lCDocfzuCkHqj8k0FpZqO+UIaKNA==
forwarded@0.2.0:
version "0.2.0"
@ -696,6 +576,11 @@ has-yarn@^2.1.0:
resolved "https://registry.yarnpkg.com/has-yarn/-/has-yarn-2.1.0.tgz#137e11354a7b5bf11aa5cb649cf0c6f3ff2b2e77"
integrity sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw==
he@1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f"
integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==
htmlparser2@^6.1.0:
version "6.1.0"
resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-6.1.0.tgz#c4d762b6c3371a05dbe65e94ae43a9f845fb8fb7"
@ -892,11 +777,6 @@ make-dir@^3.0.0:
dependencies:
semver "^6.0.0"
make-error@^1.1.1:
version "1.3.6"
resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2"
integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==
media-typer@0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"
@ -977,10 +857,18 @@ negotiator@0.6.2:
resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb"
integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==
nodemon@^2.0.7:
version "2.0.13"
resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-2.0.13.tgz#67d40d3a4d5bd840aa785c56587269cfcf5d24aa"
integrity sha512-UMXMpsZsv1UXUttCn6gv8eQPhn6DR4BW+txnL3IN5IHqrCwcrT/yWHfL35UsClGXknTH79r5xbu+6J1zNHuSyA==
node-html-parser@^5.1.0:
version "5.1.0"
resolved "https://registry.yarnpkg.com/node-html-parser/-/node-html-parser-5.1.0.tgz#753f5a60cdfe6d027c15857cb817df592c18c998"
integrity sha512-l6C1Gf1o7YuxeMGa17PypEez/rj+ii3q4/NZG37nRmWSLDjHyB0WNrlE4h2UW92D0JSfUSfu+lOvxThttVe7Jw==
dependencies:
css-select "^4.1.3"
he "1.2.0"
nodemon@^2.0.14:
version "2.0.14"
resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-2.0.14.tgz#287c7a2f6cd8a18b07e94cd776ecb6a82e4ba439"
integrity sha512-frcpDx+PviKEQRSYzwhckuO2zoHcBYLHI754RE9z5h1RGtrngerc04mLpQQCPWBkH/2ObrX7We9YiwVSYZpFJQ==
dependencies:
chokidar "^3.2.2"
debug "^3.2.6"
@ -1247,19 +1135,6 @@ signal-exit@^3.0.2:
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.4.tgz#366a4684d175b9cab2081e3681fda3747b6c51d7"
integrity sha512-rqYhcAnZ6d/vTPGghdrw7iumdcbXpsk1b8IG/rz+VWV51DM0p7XCtMoJ3qhPLIbp3tvyt3pKRbaaEMZYpHto8Q==
source-map-support@^0.5.17:
version "0.5.20"
resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.20.tgz#12166089f8f5e5e8c56926b377633392dd2cb6c9"
integrity sha512-n1lZZ8Ve4ksRqizaBQgxXDgKwttHDhyfQjA6YZZn8+AroHbsIz+JjwxQDxbp+7y5OYCI8t1Yk7etjD9CRd2hIw==
dependencies:
buffer-from "^1.0.0"
source-map "^0.6.0"
source-map@^0.6.0:
version "0.6.1"
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
"statuses@>= 1.5.0 < 2", statuses@~1.5.0:
version "1.5.0"
resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c"
@ -1324,18 +1199,6 @@ touch@^3.1.0:
dependencies:
nopt "~1.0.10"
ts-node@^9.1.1:
version "9.1.1"
resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-9.1.1.tgz#51a9a450a3e959401bda5f004a72d54b936d376d"
integrity sha512-hPlt7ZACERQGf03M253ytLY3dHbGNGrAq9qIHWUY9XHYl1z7wYngSr3OQ5xmui8o2AaxsONxIzjafLUiWBo1Fg==
dependencies:
arg "^4.1.0"
create-require "^1.1.0"
diff "^4.0.1"
make-error "^1.1.1"
source-map-support "^0.5.17"
yn "3.1.1"
tslib@^2.2.0:
version "2.3.1"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.1.tgz#e8a335add5ceae51aa261d32a490158ef042ef01"
@ -1361,11 +1224,6 @@ typedarray-to-buffer@^3.1.5:
dependencies:
is-typedarray "^1.0.0"
typescript@^4.2.3:
version "4.4.3"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.4.3.tgz#bdc5407caa2b109efd4f82fe130656f977a29324"
integrity sha512-4xfscpisVgqqDfPaJo5vkd+Qd/ItkoagnHpufr+i2QCHBsNYp+G7UAoyFl8aPtx879u38wPV65rZ8qbGZijalA==
undefsafe@^2.0.3:
version "2.0.3"
resolved "https://registry.yarnpkg.com/undefsafe/-/undefsafe-2.0.3.tgz#6b166e7094ad46313b2202da7ecc2cd7cc6e7aae"
@ -1462,8 +1320,3 @@ yallist@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"
integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==
yn@3.1.1:
version "3.1.1"
resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50"
integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==

Loading…
Cancel
Save