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.
aruppi-api/src/controllers/DirectoryController.ts

436 lines
12 KiB
TypeScript

import { NextFunction, Request, Response } from 'express';
import { requestGot } from '../utils/requestCall';
import AnimeModel, { Anime } from '../database/models/anime.model';
import GenreModel, { Genre } from '../database/models/genre.model';
import util from 'util';
import { hashStringMd5 } from '../utils/util';
import {
animeExtraInfo,
getAnimeVideoPromo,
getAnimeCharacters,
getRelatedAnimesFLV,
getRelatedAnimesMAL,
} from '../utils/util';
import urls from '../utils/urls';
import { redisClient } from '../database/connection';
// @ts-ignore
redisClient.get = util.promisify(redisClient.get);
/*
DirectoryController - async functions controlling the directory
in the database of MongoDB, functions like getAllDirectory from the DB
other functions with realation to the directory, like the season and stuff.
*/
interface TypeAnime {
title: string;
image: string;
genres: string[];
}
interface Season {
title: string;
image: string;
malink: string;
}
interface Archive {
year: string;
seasons: string[];
}
export default class DirectoryController {
async getAllDirectory(req: Request, res: Response, next: NextFunction) {
const { genres } = req.params;
try {
if (genres === 'sfw') {
await AnimeModel.find(
{
genres: { $nin: ['ecchi', 'Ecchi'] },
},
(err: any, docs: Anime[]) => {
let directory: any[] = [];
for (const item of docs) {
directory.push({
id: item.id,
title: item.title,
mal_id: item.mal_id,
poster: item.poster,
type: item.type,
genres: item.genres,
state: item.state,
score: item.score,
source: item.source,
description: item.description,
});
}
if (directory.length > 0) {
res.status(200).json({ directory });
} else {
res.status(500).json({ message: 'Aruppi lost in the shell' });
}
},
);
} else {
await AnimeModel.find((err: any, docs: Anime[]) => {
let directory: any[] = [];
for (const item of docs) {
directory.push({
id: item.id,
title: item.title,
mal_id: item.mal_id,
poster: item.poster,
type: item.type,
genres: item.genres,
state: item.state,
score: item.score,
source: item.source,
description: item.description,
});
}
if (directory.length > 0) {
res.status(200).json({ directory });
} else {
res.status(500).json({ message: 'Aruppi lost in the shell' });
}
});
}
} catch (err) {
return next(err);
}
}
async getSeason(req: Request, res: Response, next: NextFunction) {
const { year, type } = req.params;
let data: any;
try {
const resultQueryRedis: any = await redisClient.get(
`season_${hashStringMd5(`${year}:${type}`)}`,
);
if (resultQueryRedis) {
const resultRedis: any = JSON.parse(resultQueryRedis);
return res.status(200).json(resultRedis);
} else {
data = await requestGot(`${urls.BASE_JIKAN}season/${year}/${type}`, {
scrapy: false,
parse: true,
});
}
} catch (err) {
return next(err);
}
const season: TypeAnime[] = data.anime.map((item: any) => {
return {
title: item.title,
image: item.image_url,
genres: item.genres.map((genre: any) => genre.name),
};
});
if (season.length > 0) {
/* Set the key in the redis cache. */
redisClient.set(
`season_${hashStringMd5(`${year}:${type}`)}`,
JSON.stringify({ season }),
);
/* After 24hrs expire the key. */
redisClient.expireat(
`season_${hashStringMd5(`${year}:${type}`)}`,
parseInt(`${+new Date() / 1000}`, 10) + 7200,
);
res.status(200).json({
season,
});
} else {
res.status(500).json({ message: 'Aruppi lost in the shell' });
}
}
async allSeasons(req: Request, res: Response, next: NextFunction) {
let data: any;
try {
const resultQueryRedis: any = await redisClient.get(
`allSeasons_${hashStringMd5('allSeasons')}`,
);
if (resultQueryRedis) {
const resultRedis: any = JSON.parse(resultQueryRedis);
return res.status(200).json(resultRedis);
} else {
data = await requestGot(`${urls.BASE_JIKAN}season/archive`, {
parse: true,
scrapy: false,
});
}
} catch (err) {
return next(err);
}
const archive: Archive[] = data.archive.map((item: any) => {
return {
year: item.year,
seasons: item.seasons,
};
});
if (archive.length > 0) {
/* Set the key in the redis cache. */
redisClient.set(
`allSeasons_${hashStringMd5('allSeasons')}`,
JSON.stringify({ archive }),
);
/* After 24hrs expire the key. */
redisClient.expireat(
`allSeasons_${hashStringMd5('allSeasons')}`,
parseInt(`${+new Date() / 1000}`, 10) + 7200,
);
res.status(200).json({ archive });
} else {
res.status(500).json({ message: 'Aruppi lost in the shell' });
}
}
async laterSeasons(req: Request, res: Response, next: NextFunction) {
let data: any;
try {
const resultQueryRedis: any = await redisClient.get(
`laterSeasons_${hashStringMd5('laterSeasons')}`,
);
if (resultQueryRedis) {
const resultRedis: any = JSON.parse(resultQueryRedis);
return res.status(200).json(resultRedis);
} else {
data = await requestGot(`${urls.BASE_JIKAN}season/later`, {
parse: true,
scrapy: false,
});
}
} catch (err) {
return next(err);
}
const future: Season[] = data.anime.map((item: any) => {
return {
title: item.title,
image: item.image_url,
malink: item.url,
};
});
if (future.length > 0) {
/* Set the key in the redis cache. */
redisClient.set(
`laterSeasons_${hashStringMd5('laterSeasons')}`,
JSON.stringify({ future }),
);
/* After 24hrs expire the key. */
redisClient.expireat(
`laterSeasons_${hashStringMd5('laterSeasons')}`,
parseInt(`${+new Date() / 1000}`, 10) + 7200,
);
res.status(200).json({ future });
} else {
res.status(500).json({ message: 'Aruppi lost in the shell' });
}
}
async getMoreInfo(req: Request, res: Response, next: NextFunction) {
const { title } = req.params;
let resultQuery: Anime | null;
let resultAnime: any;
try {
const resultQueryRedis: any = await redisClient.get(
`moreInfo_${hashStringMd5(title)}`,
);
if (resultQueryRedis) {
const resultRedis: any = JSON.parse(resultQueryRedis);
return res.status(200).json(resultRedis);
} else {
resultQuery = await AnimeModel.findOne({
$or: [{ title: { $eq: title } }, { title: { $eq: `${title} (TV)` } }],
});
const extraInfo: any = await animeExtraInfo(resultQuery!.mal_id);
switch (resultQuery?.source) {
case 'animeflv':
resultAnime = {
title: resultQuery?.title,
poster: resultQuery?.poster,
synopsis: resultQuery?.description,
status: !extraInfo.aired.to ? 'En emisión' : 'Finalizado',
type: resultQuery?.type,
rating: resultQuery?.score,
genres: resultQuery?.genres,
moreInfo: [extraInfo],
promo: await getAnimeVideoPromo(resultQuery!.mal_id),
characters: await getAnimeCharacters(resultQuery!.mal_id),
related: await getRelatedAnimesFLV(resultQuery!.id),
};
break;
case 'jkanime':
resultAnime = {
title: resultQuery?.title,
poster: resultQuery?.poster,
synopsis: resultQuery?.description,
status: !extraInfo.aired.to ? 'En emisión' : 'Finalizado',
type: resultQuery?.type,
rating: resultQuery?.score,
genres: resultQuery?.genres,
moreInfo: [extraInfo],
promo: await getAnimeVideoPromo(resultQuery!.mal_id),
characters: await getAnimeCharacters(resultQuery!.mal_id),
related: await getRelatedAnimesMAL(resultQuery!.mal_id),
};
break;
case 'monoschinos':
resultAnime = {
title: resultQuery?.title,
poster: resultQuery?.poster,
synopsis: resultQuery?.description,
status: !extraInfo.aired.to ? 'En emisión' : 'Finalizado',
type: resultQuery?.type,
rating: resultQuery?.score,
genres: resultQuery?.genres,
moreInfo: [extraInfo],
promo: await getAnimeVideoPromo(resultQuery!.mal_id),
characters: await getAnimeCharacters(resultQuery!.mal_id),
related: await getRelatedAnimesMAL(resultQuery!.mal_id),
};
break;
default:
resultAnime = undefined;
break;
}
}
} catch (err) {
return next(err);
}
if (resultAnime) {
/* Set the key in the redis cache. */
redisClient.set(
`moreInfo_${hashStringMd5(title)}`,
JSON.stringify(resultAnime),
);
/* After 24hrs expire the key. */
redisClient.expireat(
`moreInfo_${hashStringMd5(title)}`,
parseInt(`${+new Date() / 1000}`, 10) + 7200,
);
res.status(200).json(resultAnime);
} else {
res.status(500).json({ message: 'Aruppi lost in the shell' });
}
}
async search(req: Request, res: Response, next: NextFunction) {
const { title } = req.params;
let results: Anime[] | null;
try {
results = await AnimeModel.find({
title: { $regex: new RegExp(title, 'i') },
});
} catch (err) {
return next(err);
}
const resultAnimes: any[] = results.map((item: any) => {
return {
id: item.id,
title: item.title,
type: item.type,
image: item.poster,
};
});
if (resultAnimes.length > 0) {
res.status(200).json({ search: resultAnimes });
} else {
res.status(500).json({ message: 'Aruppi lost in the shell' });
}
}
async getAnimeGenres(req: Request, res: Response, next: NextFunction) {
const { genre, order, page } = req.params;
let data: Genre[];
let resultReq: any;
try {
if (genre === undefined && order === undefined && page === undefined) {
data = await GenreModel.find();
} else {
if (page !== undefined) {
resultReq = await requestGot(
`${urls.BASE_ANIMEFLV_JELU}Genres/${genre}/${order}/${page}`,
{ parse: true, scrapy: false },
);
} else {
resultReq = await requestGot(
`${urls.BASE_ANIMEFLV_JELU}Genres/${genre}/${order}/1`,
{ parse: true, scrapy: false },
);
}
}
} catch (err) {
return next(err);
}
const animes: any[] = resultReq.animes.map((item: any) => {
return {
id: item.id,
title: item.title.trim(),
mention: genre,
page: page,
poster: item.poster,
banner: item.banner,
synopsis: item.synopsis,
type: item.type,
rating: item.rating,
genre: item.genre,
};
});
if (animes.length > 0) {
res.status(200).json({ animes });
} else {
res.status(500).json({ message: 'Aruppi lost in the shell' });
}
}
}