|
|
|
@ -4,7 +4,6 @@ import AnimeModel, {Anime} from '../database/models/anime.model';
|
|
|
|
|
import crypto from 'crypto';
|
|
|
|
|
import util from 'util';
|
|
|
|
|
import { redisClient } from '../database/connection';
|
|
|
|
|
import { stderr } from 'process';
|
|
|
|
|
|
|
|
|
|
// @ts-ignore
|
|
|
|
|
redisClient.get = util.promisify(redisClient.get);
|
|
|
|
@ -35,7 +34,7 @@ interface RelatedAnime {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export const animeExtraInfo = async (mal_id: number) => {
|
|
|
|
|
let info: any;
|
|
|
|
|
let data: any;
|
|
|
|
|
let broadcast: any;
|
|
|
|
|
|
|
|
|
|
const airDay: any = {
|
|
|
|
@ -69,40 +68,40 @@ export const animeExtraInfo = async (mal_id: number) => {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
info = await requestGot(`${urls.BASE_JIKAN}anime/${mal_id}`, {
|
|
|
|
|
data = await requestGot(`${urls.BASE_JIKAN}anime/${mal_id}`, {
|
|
|
|
|
parse: true,
|
|
|
|
|
scrapy: false,
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if (info.data.airing) {
|
|
|
|
|
broadcast = info.data.broadcast.string.split('at')[0].trim().toLowerCase() || null;
|
|
|
|
|
if (data.broadcast) {
|
|
|
|
|
broadcast = data.broadcast.split('at')[0].trim().toLowerCase() || null;
|
|
|
|
|
}
|
|
|
|
|
} catch (err) {
|
|
|
|
|
return err;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (airDay.hasOwnProperty(broadcast)) {
|
|
|
|
|
info.data.broadcast = airDay[broadcast];
|
|
|
|
|
data.broadcast = airDay[broadcast];
|
|
|
|
|
} else {
|
|
|
|
|
info.data.broadcast = null;
|
|
|
|
|
data.broadcast = null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const formattedObject: any = {
|
|
|
|
|
titleJapanese: info.data.titles.find((x: { type: string; }) => x.type === "Default").title,
|
|
|
|
|
source: info.data.source,
|
|
|
|
|
totalEpisodes: info.data.episodes,
|
|
|
|
|
titleJapanese: data.title_japanese,
|
|
|
|
|
source: data.source,
|
|
|
|
|
totalEpisodes: data.episodes,
|
|
|
|
|
aired: {
|
|
|
|
|
from: info.data.aired.from,
|
|
|
|
|
to: info.data.aired.to,
|
|
|
|
|
from: data.aired.from,
|
|
|
|
|
to: data.aired.to,
|
|
|
|
|
},
|
|
|
|
|
duration: info.data.duration.split('per')[0],
|
|
|
|
|
rank: info.data.rank,
|
|
|
|
|
broadcast: info.data.broadcast,
|
|
|
|
|
producers: info.data.producers.map((item: any) => item.name) || null,
|
|
|
|
|
licensors: info.data.licensors.map((item: any) => item.name) || null,
|
|
|
|
|
studios: info.data.studios.map((item: any) => item.name) || null,
|
|
|
|
|
openingThemes: info.data.opening_themes || null,
|
|
|
|
|
endingThemes: info.data.ending_themes || null,
|
|
|
|
|
duration: data.duration.split('per')[0],
|
|
|
|
|
rank: data.rank,
|
|
|
|
|
broadcast: data.broadcast,
|
|
|
|
|
producers: data.producers.map((item: any) => item.name) || null,
|
|
|
|
|
licensors: data.licensors.map((item: any) => item.name) || null,
|
|
|
|
|
studios: data.studios.map((item: any) => item.name) || null,
|
|
|
|
|
openingThemes: data.opening_themes || null,
|
|
|
|
|
endingThemes: data.ending_themes || null,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if (formattedObject) {
|
|
|
|
@ -129,12 +128,12 @@ export const animeExtraInfo = async (mal_id: number) => {
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export const getAnimeVideoPromo = async (mal_id: number) => {
|
|
|
|
|
let info: any;
|
|
|
|
|
let data: any;
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
if (redisClient.connected) {
|
|
|
|
|
const resultQueryRedis: any = await redisClient.get(
|
|
|
|
|
`getMALpromoInfo_${mal_id}`,
|
|
|
|
|
`promoInfo_${hashStringMd5(`${mal_id}`)}`,
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
if (resultQueryRedis) {
|
|
|
|
@ -144,7 +143,7 @@ export const getAnimeVideoPromo = async (mal_id: number) => {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
info = await requestGot(`${urls.BASE_JIKAN}anime/${mal_id}/videos`, {
|
|
|
|
|
data = await requestGot(`${urls.BASE_JIKAN}anime/${mal_id}/videos`, {
|
|
|
|
|
parse: true,
|
|
|
|
|
scrapy: false,
|
|
|
|
|
});
|
|
|
|
@ -152,11 +151,11 @@ export const getAnimeVideoPromo = async (mal_id: number) => {
|
|
|
|
|
return err;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const promo: Promo[] = info.data.promo.map((item: any) => {
|
|
|
|
|
const promo: Promo[] = data.promo.map((item: Promo) => {
|
|
|
|
|
return {
|
|
|
|
|
title: item.title,
|
|
|
|
|
previewImage: item.trailer.images.image_url,
|
|
|
|
|
videoURL: item.trailer.url,
|
|
|
|
|
previewImage: item.image_url,
|
|
|
|
|
videoURL: item.video_url,
|
|
|
|
|
};
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
@ -165,15 +164,15 @@ export const getAnimeVideoPromo = async (mal_id: number) => {
|
|
|
|
|
/* Set the key in the redis cache. */
|
|
|
|
|
|
|
|
|
|
redisClient.set(
|
|
|
|
|
`getMALpromoInfo_${mal_id}`,
|
|
|
|
|
`promoInfo_${hashStringMd5(`${mal_id}`)}`,
|
|
|
|
|
JSON.stringify(promo),
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
/* After 2hrs expire the key. */
|
|
|
|
|
/* After 24hrs expire the key. */
|
|
|
|
|
|
|
|
|
|
redisClient.expire(
|
|
|
|
|
`getMALpromoInfo_${mal_id}`,
|
|
|
|
|
7200,
|
|
|
|
|
redisClient.expireat(
|
|
|
|
|
`promoInfo_${hashStringMd5(`${mal_id}`)}`,
|
|
|
|
|
parseInt(`${+new Date() / 1000}`, 10) + 7200,
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -184,7 +183,7 @@ export const getAnimeVideoPromo = async (mal_id: number) => {
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export const getAnimeCharacters = async (mal_id: number) => {
|
|
|
|
|
let info: any;
|
|
|
|
|
let data: any;
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
if (redisClient.connected) {
|
|
|
|
@ -199,19 +198,19 @@ export const getAnimeCharacters = async (mal_id: number) => {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
info = await requestGot(
|
|
|
|
|
`${urls.BASE_JIKAN}anime/${mal_id}/characters`,
|
|
|
|
|
data = await requestGot(
|
|
|
|
|
`${urls.BASE_JIKAN}anime/${mal_id}/characters_staff`,
|
|
|
|
|
{ parse: true, scrapy: false },
|
|
|
|
|
);
|
|
|
|
|
} catch (err) {
|
|
|
|
|
return err;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const characters: Character[] = info.data.map((item: any) => {
|
|
|
|
|
const characters: Character[] = data.characters.map((item: any) => {
|
|
|
|
|
return {
|
|
|
|
|
id: item.character.mal_id,
|
|
|
|
|
name: item.character.name,
|
|
|
|
|
image: item.character.images.jpg.image_url,
|
|
|
|
|
id: item.mal_id,
|
|
|
|
|
name: item.name,
|
|
|
|
|
image: item.image_url,
|
|
|
|
|
role: item.role,
|
|
|
|
|
};
|
|
|
|
|
});
|
|
|
|
@ -263,12 +262,12 @@ const getPosterAndType = async (
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export const getRelatedAnimesMAL = async (mal_id: number) => {
|
|
|
|
|
let info: any;
|
|
|
|
|
let $: cheerio.Root;
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
if (redisClient.connected) {
|
|
|
|
|
const resultQueryRedis: any = await redisClient.get(
|
|
|
|
|
`getRelatedMAL_${mal_id}`,
|
|
|
|
|
`getRelatedMAL_${hashStringMd5(`${mal_id}`)}`,
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
if (resultQueryRedis) {
|
|
|
|
@ -278,31 +277,41 @@ export const getRelatedAnimesMAL = async (mal_id: number) => {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
info = await requestGot(`${urls.BASE_JIKAN}anime/${mal_id}/relations`, {
|
|
|
|
|
parse: true,
|
|
|
|
|
scrapy: false,
|
|
|
|
|
$ = await requestGot(`https://myanimelist.net/anime/${mal_id}`, {
|
|
|
|
|
parse: false,
|
|
|
|
|
scrapy: true,
|
|
|
|
|
});
|
|
|
|
|
} catch (err) {
|
|
|
|
|
stderr.write(`Error on getRelatedAnimesMAL http on mal_id: ${mal_id}\n`)
|
|
|
|
|
return err;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const relatedAnimes = []
|
|
|
|
|
for (const relation_entry of info.data) {
|
|
|
|
|
for (const entry of relation_entry.entry){
|
|
|
|
|
if (entry.type != "anime")
|
|
|
|
|
break;
|
|
|
|
|
const queryRes: Anime | null = await AnimeModel.findOne({
|
|
|
|
|
mal_id: {$eq: entry.mal_id}
|
|
|
|
|
let listRelated: any = {};
|
|
|
|
|
let relatedAnimes: RelatedAnime[] = [];
|
|
|
|
|
|
|
|
|
|
if ($('table.anime_detail_related_anime').length > 0) {
|
|
|
|
|
$('table.anime_detail_related_anime')
|
|
|
|
|
.find('tbody tr')
|
|
|
|
|
.each((index: number, element: any) => {
|
|
|
|
|
if ($(element).find('td').eq(0).text() !== 'Adaptation:') {
|
|
|
|
|
listRelated[$(element).find('td').eq(1).text()] = $(element)
|
|
|
|
|
.find('td')
|
|
|
|
|
.children('a')
|
|
|
|
|
.attr('href');
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
if (queryRes == null)
|
|
|
|
|
break
|
|
|
|
|
|
|
|
|
|
for (const related in listRelated) {
|
|
|
|
|
let posterUrl: any = await getPosterAndType(
|
|
|
|
|
undefined,
|
|
|
|
|
listRelated[related].split('/')[2],
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
if (posterUrl !== '') {
|
|
|
|
|
relatedAnimes.push({
|
|
|
|
|
title: queryRes!.title,
|
|
|
|
|
type: queryRes?.type,
|
|
|
|
|
poster: queryRes?.poster
|
|
|
|
|
})
|
|
|
|
|
title: related,
|
|
|
|
|
type: posterUrl[1],
|
|
|
|
|
poster: posterUrl[0],
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -311,20 +320,23 @@ export const getRelatedAnimesMAL = async (mal_id: number) => {
|
|
|
|
|
/* Set the key in the redis cache. */
|
|
|
|
|
|
|
|
|
|
redisClient.set(
|
|
|
|
|
`getRelatedMAL_${mal_id}`,
|
|
|
|
|
`getRelatedMAL_${hashStringMd5(`${mal_id}`)}`,
|
|
|
|
|
JSON.stringify(relatedAnimes),
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
/* After 1hr expire the key. */
|
|
|
|
|
/* After 24hrs expire the key. */
|
|
|
|
|
|
|
|
|
|
redisClient.expire(
|
|
|
|
|
`getRelatedMAL_${mal_id}`,
|
|
|
|
|
3600,
|
|
|
|
|
redisClient.expireat(
|
|
|
|
|
`getRelatedMAL_${hashStringMd5(`${mal_id}`)}`,
|
|
|
|
|
parseInt(`${+new Date() / 1000}`, 10) + 7200,
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return relatedAnimes;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
return [];
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export const jkanimeInfo = async (id: string | undefined, mal_id: number) => {
|
|
|
|
@ -459,7 +471,7 @@ export const monoschinosInfo = async (
|
|
|
|
|
id: string | undefined,
|
|
|
|
|
mal_id: number,
|
|
|
|
|
) => {
|
|
|
|
|
let info;
|
|
|
|
|
let $: cheerio.Root;
|
|
|
|
|
let episodeList: any[] = [];
|
|
|
|
|
let extraInfo: any;
|
|
|
|
|
|
|
|
|
@ -476,9 +488,9 @@ export const monoschinosInfo = async (
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
info = await requestGot(`${urls.BASE_ARUPPI_MONOSCHINOS}anime/${id}`, {
|
|
|
|
|
scrapy: false,
|
|
|
|
|
parse: true,
|
|
|
|
|
$ = await requestGot(`${urls.BASE_MONOSCHINOS}anime/${id}`, {
|
|
|
|
|
scrapy: true,
|
|
|
|
|
parse: false,
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
/* Extra info of the anime */
|
|
|
|
@ -487,6 +499,7 @@ export const monoschinosInfo = async (
|
|
|
|
|
console.log(err);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ($!) {
|
|
|
|
|
if (extraInfo) {
|
|
|
|
|
let broadCastDate = new Date();
|
|
|
|
|
let dd: number, mm: string | number, yyyy: number;
|
|
|
|
@ -541,12 +554,25 @@ export const monoschinosInfo = async (
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (const anime of info.episodes) {
|
|
|
|
|
$!('.SerieCaps a').each((index: number, element: cheerio.Element) => {
|
|
|
|
|
let episode: number;
|
|
|
|
|
|
|
|
|
|
$(element)
|
|
|
|
|
.attr('href')
|
|
|
|
|
?.split('-')
|
|
|
|
|
.forEach((item: any) => {
|
|
|
|
|
if (!isNaN(item)) {
|
|
|
|
|
episode = parseInt(item);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
episodeList.push({
|
|
|
|
|
episode: anime.no,
|
|
|
|
|
id: `ver/${anime.id}`,
|
|
|
|
|
episode: episode!,
|
|
|
|
|
id: `${$(element).attr('href')?.split('/')[3]}/${
|
|
|
|
|
$(element).attr('href')?.split('/')[4]
|
|
|
|
|
}`,
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (episodeList.length > 0) {
|
|
|
|
|
if (redisClient.connected) {
|
|
|
|
@ -569,7 +595,9 @@ export const monoschinosInfo = async (
|
|
|
|
|
} else {
|
|
|
|
|
return undefined;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
return undefined;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export const tioanimeInfo = async (id: string | undefined, mal_id: number) => {
|
|
|
|
@ -594,7 +622,6 @@ export const tioanimeInfo = async (id: string | undefined, mal_id: number) => {
|
|
|
|
|
$ = await requestGot(`${urls.BASE_TIOANIME}anime/${id}`, {
|
|
|
|
|
scrapy: true,
|
|
|
|
|
parse: false,
|
|
|
|
|
spoof: true,
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
/* Extra info of the anime */
|
|
|
|
@ -698,7 +725,7 @@ export const tioanimeInfo = async (id: string | undefined, mal_id: number) => {
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export const videoServersMonosChinos = async (id: string) => {
|
|
|
|
|
let $;
|
|
|
|
|
let $: cheerio.Root;
|
|
|
|
|
let videoServers: any[] = [];
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
@ -714,21 +741,51 @@ export const videoServersMonosChinos = async (id: string) => {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$ = await requestGot(`${urls.BASE_ARUPPI_MONOSCHINOS}${id}`, {
|
|
|
|
|
scrapy: false,
|
|
|
|
|
parse: true,
|
|
|
|
|
$ = await requestGot(`${urls.BASE_MONOSCHINOS}${id}`, {
|
|
|
|
|
scrapy: true,
|
|
|
|
|
parse: false,
|
|
|
|
|
});
|
|
|
|
|
} catch (err) {
|
|
|
|
|
return err;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (const server of $.videos) {
|
|
|
|
|
let videoNames: string[] = $('.TPlayerNv li')
|
|
|
|
|
.map((index: number, element: cheerio.Element) => {
|
|
|
|
|
return $(element).attr('title');
|
|
|
|
|
})
|
|
|
|
|
.get();
|
|
|
|
|
|
|
|
|
|
videoServers.push({
|
|
|
|
|
id: videoNames[0].toLowerCase(),
|
|
|
|
|
url: decodeURIComponent(
|
|
|
|
|
$('.TPlayer div iframe').attr('src')?.split('url=')[1]!,
|
|
|
|
|
).split('&id')[0],
|
|
|
|
|
direct: false,
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const videoContainer: any = $('.TPlayer div').text();
|
|
|
|
|
|
|
|
|
|
$(videoContainer).each((index: number, element: cheerio.Element) => {
|
|
|
|
|
let video: any = $(element).attr('src');
|
|
|
|
|
|
|
|
|
|
if (video) {
|
|
|
|
|
video = video.split('url=')[1];
|
|
|
|
|
video = decodeURIComponent(video);
|
|
|
|
|
video = video.split('&id')[0];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (video) {
|
|
|
|
|
videoNames.forEach((value: string) => {
|
|
|
|
|
if (video.includes(value.toLowerCase())) {
|
|
|
|
|
videoServers.push({
|
|
|
|
|
id: server.title,
|
|
|
|
|
url: server.url.replace("https://monoschinos2.com/reproductor?url=", ""),
|
|
|
|
|
id: value.toLowerCase(),
|
|
|
|
|
url: video,
|
|
|
|
|
direct: false,
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if (videoServers.length > 0) {
|
|
|
|
|
if (redisClient.connected) {
|
|
|
|
@ -774,7 +831,6 @@ export const videoServersTioAnime = async (id: string) => {
|
|
|
|
|
$ = await requestGot(`${urls.BASE_TIOANIME}${id}`, {
|
|
|
|
|
scrapy: true,
|
|
|
|
|
parse: false,
|
|
|
|
|
spoof: true,
|
|
|
|
|
});
|
|
|
|
|
} catch (err) {
|
|
|
|
|
return err;
|
|
|
|
@ -931,7 +987,7 @@ async function desuServerUrl(url: string) {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$ = await requestGot(url, {scrapy: true, parse: false, spoof: true});
|
|
|
|
|
$ = await requestGot(url, { scrapy: true, parse: false });
|
|
|
|
|
} catch (err) {
|
|
|
|
|
return err;
|
|
|
|
|
}
|
|
|
|
@ -1023,7 +1079,7 @@ export function getThemes(themes: any[]) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export const imageUrlToBase64 = async (url: string) => {
|
|
|
|
|
let img: any = await requestGot(url,{spoof:false});
|
|
|
|
|
let img: any = await requestGot(url);
|
|
|
|
|
return img.rawBody.toString('base64');
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|