import urls from './urls' ; import { requestGot } from './requestCall' ; import AnimeModel , { Anime } from '../database/models/anime.model' ; import crypto from 'crypto' ; import util from 'util' ; import { redisClient } from '../database/connection' ; redisClient . get = util . promisify ( redisClient . get ) ; interface Promo { title : string ; image_url : string ; video_url : string ; } interface Character { id : number ; name : string ; image : string ; role : string ; } interface RelatedAnime { title : string ; type : string ; poster : string ; } export const animeExtraInfo = async ( mal_id ) => { let data ; let broadcast ; const airDay = { mondays : 'Lunes' , monday : 'Lunes' , tuesdays : 'Martes' , tuesday : 'Martes' , wednesdays : 'Miércoles' , wednesday : 'Miércoles' , thursdays : 'Jueves' , thursday : 'Jueves' , fridays : 'Viernes' , friday : 'Viernes' , saturdays : 'Sábados' , saturday : 'Sábados' , sundays : 'Domingos' , sunday : 'Domingos' , default : 'Sin emisión' , } ; try { if ( redisClient . connected ) { const resultQueryRedis = await redisClient . get ( `extraInfo_${ hashStringMd5 ( `${ mal_id }` ) }` ) ; if ( resultQueryRedis ) { const resultRedis = JSON . parse ( resultQueryRedis ) ; return resultRedis ; } } data = await requestGot ( `${ urls . BASE_JIKAN }anime/${ mal_id }` , { parse : true , scrapy : false , } ) ; if ( data . broadcast ) { broadcast = data . broadcast . split ( 'at' ) [ 0 ] . trim ( ) . toLowerCase ( ) || null ; } } catch ( err ) { return err ; } if ( airDay . hasOwnProperty ( broadcast ) ) { data . broadcast = airDay [ broadcast ] ; } else { data . broadcast = null ; } const formattedObject = { titleJapanese : data . title_japanese , source : data . source , totalEpisodes : data . episodes , aired : { from : data . aired . from , to : data . aired . to , } , duration : data . duration . split ( 'per' ) [ 0 ] , rank : data . rank , broadcast : data . broadcast , producers : data . producers . map ( ( item ) => item . name ) || null , licensors : data . licensors . map ( ( item ) => item . name ) || null , studios : data . studios . map ( ( item ) => item . name ) || null , openingThemes : data . opening_themes || null , endingThemes : data . ending_themes || null , } ; if ( formattedObject ) { if ( redisClient . connected ) { redisClient . set ( `extraInfo_${ hashStringMd5 ( `${ mal_id }` ) }` , JSON . stringify ( formattedObject ) ) ; redisClient . expireat ( `extraInfo_${ hashStringMd5 ( `${ mal_id }` ) }` , parseInt ( `${ + new Date ( ) / 1000 }` , 10 ) + 7200 ) ; } return formattedObject ; } else { return null ; } } ; export const getAnimeVideoPromo = async ( mal_id ) => { let data ; try { if ( redisClient . connected ) { const resultQueryRedis = await redisClient . get ( `promoInfo_${ hashStringMd5 ( `${ mal_id }` ) }` ) ; if ( resultQueryRedis ) { const resultRedis = JSON . parse ( resultQueryRedis ) ; return resultRedis ; } } data = await requestGot ( `${ urls . BASE_JIKAN }anime/${ mal_id }/videos` , { parse : true , scrapy : false , } ) ; } catch ( err ) { return err ; } const promo = data . promo . map ( ( item ) => { return { title : item . title , previewImage : item . image_url , videoURL : item . video_url , } ; } ) ; if ( promo . length > 0 ) { if ( redisClient . connected ) { redisClient . set ( `promoInfo_${ hashStringMd5 ( `${ mal_id }` ) }` , JSON . stringify ( promo ) ) ; redisClient . expireat ( `promoInfo_${ hashStringMd5 ( `${ mal_id }` ) }` , parseInt ( `${ + new Date ( ) / 1000 }` , 10 ) + 7200 ) ; } return promo ; } else { return null ; } } ; export const getAnimeCharacters = async ( mal_id ) => { let data ; try { if ( redisClient . connected ) { const resultQueryRedis = await redisClient . get ( `charactersInfo_${ hashStringMd5 ( `${ mal_id }` ) }` ) ; if ( resultQueryRedis ) { const resultRedis = JSON . parse ( resultQueryRedis ) ; return resultRedis ; } } data = await requestGot ( `${ urls . BASE_JIKAN }anime/${ mal_id }/characters_staff` , { parse : true , scrapy : false } ) ; } catch ( err ) { return err ; } const characters = data . characters . map ( ( item ) => { return { id : item . mal_id , name : item . name , image : item . image_url , role : item . role , } ; } ) ; if ( characters . length > 0 ) { if ( redisClient . connected ) { redisClient . set ( `charactersInfo_${ hashStringMd5 ( `${ mal_id }` ) }` , JSON . stringify ( characters ) ) ; redisClient . expireat ( `charactersInfo_${ hashStringMd5 ( `${ mal_id }` ) }` , parseInt ( `${ + new Date ( ) / 1000 }` , 10 ) + 7200 ) ; } return characters ; } else { return null ; } } ; const getPosterAndType = async ( id , mal_id ) => { if ( id ) { const queryRes = await AnimeModel . findOne ( { id : { $eq : id } , } ) ; return [ queryRes ?. poster , queryRes ?. type ] ; } if ( mal_id ) { const queryRes = await AnimeModel . findOne ( { mal_id : { $eq : mal_id } , } ) ; return [ queryRes ?. poster , queryRes ?. type ] ; } return '' ; } ; export const getRelatedAnimesMAL = async ( mal_id ) => { let $ ; try { if ( redisClient . connected ) { const resultQueryRedis = await redisClient . get ( `getRelatedMAL_${ hashStringMd5 ( `${ mal_id }` ) }` ) ; if ( resultQueryRedis ) { const resultRedis = JSON . parse ( resultQueryRedis ) ; return resultRedis ; } } $ = await requestGot ( `https://myanimelist.net/anime/${ mal_id }` , { parse : false , scrapy : true , } ) ; } catch ( err ) { return err ; } let listRelated = { } ; let relatedAnimes = [ ] ; if ( $ ( 'table.anime_detail_related_anime' ) . length > 0 ) { $ ( 'table.anime_detail_related_anime' ) . find ( 'tbody tr' ) . each ( ( index , element ) => { if ( $ ( element ) . find ( 'td' ) . eq ( 0 ) . text ( ) !== 'Adaptation:' ) { listRelated [ $ ( element ) . find ( 'td' ) . eq ( 1 ) . text ( ) ] = $ ( element ) . find ( 'td' ) . children ( 'a' ) . attr ( 'href' ) ; } } ) ; for ( const related in listRelated ) { let posterUrl = await getPosterAndType ( undefined , listRelated [ related ] . split ( '/' ) [ 2 ] ) ; if ( posterUrl !== '' ) { relatedAnimes . push ( { title : related , type : posterUrl [ 1 ] , poster : posterUrl [ 0 ] , } ) ; } } if ( relatedAnimes . length > 0 ) { if ( redisClient . connected ) { redisClient . set ( `getRelatedMAL_${ hashStringMd5 ( `${ mal_id }` ) }` , JSON . stringify ( relatedAnimes ) ) ; redisClient . expireat ( `getRelatedMAL_${ hashStringMd5 ( `${ mal_id }` ) }` , parseInt ( `${ + new Date ( ) / 1000 }` , 10 ) + 7200 ) ; } return relatedAnimes ; } } else { return [ ] ; } } ; export const jkanimeInfo = async ( id , mal_id ) => { let $ ; let extraInfo ; let episodesList = [ ] ; let countEpisodes = [ ] ; try { if ( redisClient . connected ) { const resultQueryRedis = await redisClient . get ( `jkanimeInfo_${ hashStringMd5 ( id ! ) }` ) ; if ( resultQueryRedis ) { const resultRedis = JSON . parse ( resultQueryRedis ) ; return resultRedis ; } } $ = await requestGot ( `${ urls . BASE_JKANIME }${ id }` , { scrapy : true , parse : false , } ) ; extraInfo = ( await animeExtraInfo ( mal_id ) ) || undefined ; } catch ( err ) { console . log ( err ) ; } if ( $ ! ) { countEpisodes = $ ! ( 'div.anime__pagination a' ) . map ( ( index , element ) => { return $ ! ( element ) . text ( ) ; } ) . get ( ) ; const episodesCount = countEpisodes [ countEpisodes . length - 1 ] . split ( '-' ) [ 1 ] ; if ( extraInfo ) { let broadCastDate = new Date ( ) ; let dd , mm , yyyy ; const airDay = { Lunes : 1 , Martes : 2 , Miércoles : 3 , Jueves : 4 , Viernes : 5 , Sábados : 6 , Domingos : 7 , 'Sin emisión' : 'default' , } ; if ( ! extraInfo . aired . to ) { if ( airDay . hasOwnProperty ( extraInfo . broadcast ) ) { if ( broadCastDate . getDay ( ) < airDay [ extraInfo . broadcast ] ) { for ( let i = broadCastDate . getDay ( ) ; i < airDay [ extraInfo . broadcast ] ; i ++ ) { broadCastDate . setDate ( broadCastDate . getDate ( ) + 1 ) ; } } else { let counter = broadCastDate . getDay ( ) + 1 ; broadCastDate . setDate ( broadCastDate . getDate ( ) + 1 ) ; while ( counter !== airDay [ extraInfo . broadcast ] ) { if ( counter === 7 ) { counter = 0 ; } broadCastDate . setDate ( broadCastDate . getDate ( ) + 1 ) ; counter ++ ; } } dd = broadCastDate . getDate ( ) ; mm = broadCastDate . getMonth ( ) + 1 < 10 ? `0${ broadCastDate . getMonth ( ) + 1 }` : broadCastDate . getMonth ( ) + 1 ; yyyy = broadCastDate . getFullYear ( ) ; episodesList . push ( { nextEpisodeDate : `${ yyyy }-${ mm }-${ dd }` , } ) ; } } } for ( let i = 1 ; i <= parseInt ( episodesCount ) ; i ++ ) { episodesList . push ( { episode : i , id : `${ id }/${ i }` , } ) ; } if ( episodesList . length > 0 ) { if ( redisClient . connected ) { redisClient . set ( `jkanimeInfo_${ hashStringMd5 ( id ! ) }` , JSON . stringify ( episodesList ) ) ; redisClient . expireat ( `jkanimeInfo_${ hashStringMd5 ( id ! ) }` , parseInt ( `${ + new Date ( ) / 1000 }` , 10 ) + 7200 ) ; } return episodesList ; } else { return undefined ; } } else { return undefined ; } } ; export const monoschinosInfo = async ( id , mal_id ) => { let info ; let episodeList = [ ] ; let extraInfo ; try { if ( redisClient . connected ) { const resultQueryRedis = await redisClient . get ( `monoschinosInfo_${ hashStringMd5 ( id ! ) }` ) ; if ( resultQueryRedis ) { const resultRedis = JSON . parse ( resultQueryRedis ) ; return resultRedis ; } } info = await requestGot ( `${ urls . BASE_ARUPPI_MONOSCHINOS }anime/${ id }` , { scrapy : false , parse : true , } ) ; extraInfo = ( await animeExtraInfo ( mal_id ) ) || undefined ; } catch ( err ) { console . log ( err ) ; } if ( extraInfo ) { let broadCastDate = new Date ( ) ; let dd , mm , yyyy ; const airDay = { Lunes : 1 , Martes : 2 , Miércoles : 3 , Jueves : 4 , Viernes : 5 , Sábados : 6 , Domingos : 7 , 'Sin emisión' : 'default' , } ; if ( ! extraInfo . aired . to ) { if ( airDay . hasOwnProperty ( extraInfo . broadcast ) ) { if ( broadCastDate . getDay ( ) < airDay [ extraInfo . broadcast ] ) { for ( let i = broadCastDate . getDay ( ) ; i < airDay [ extraInfo . broadcast ] ; i ++ ) { broadCastDate . setDate ( broadCastDate . getDate ( ) + 1 ) ; } } else { let counter = broadCastDate . getDay ( ) + 1 ; broadCastDate . setDate ( broadCastDate . getDate ( ) + 1 ) ; while ( counter !== airDay [ extraInfo . broadcast ] ) { if ( counter === 7 ) { counter = 0 ; } broadCastDate . setDate ( broadCastDate . getDate ( ) + 1 ) ; counter ++ ; } } dd = broadCastDate . getDate ( ) ; mm = broadCastDate . getMonth ( ) + 1 < 10 ? `0${ broadCastDate . getMonth ( ) + 1 }` : broadCastDate . getMonth ( ) + 1 ; yyyy = broadCastDate . getFullYear ( ) ; episodeList . push ( { nextEpisodeDate : `${ yyyy }-${ mm }-${ dd }` , } ) ; } } } for ( const anime of info . episodes ) { episodeList . push ( { episode : anime . no , id : `ver/${ anime . id }` , } ) ; } if ( episodeList . length > 0 ) { if ( redisClient . connected ) { redisClient . set ( `monoschinosInfo_${ hashStringMd5 ( id ! ) }` , JSON . stringify ( episodeList ) ) ; redisClient . expireat ( `monoschinosInfo_${ hashStringMd5 ( id ! ) }` , parseInt ( `${ + new Date ( ) / 1000 }` , 10 ) + 7200 ) ; } return episodeList ; } else { return undefined ; } } ; export const tioanimeInfo = async ( id , mal_id ) => { let $ ; let episodesList = [ ] ; let anime_eps = [ ] ; let extraInfo ; try { if ( redisClient . connected ) { const resultQueryRedis = await redisClient . get ( `tioanimeInfo_${ hashStringMd5 ( id ! ) }` ) ; if ( resultQueryRedis ) { const resultRedis = JSON . parse ( resultQueryRedis ) ; return resultRedis ; } } $ = await requestGot ( `${ urls . BASE_TIOANIME }anime/${ id }` , { scrapy : true , parse : false , } ) ; extraInfo = ( await animeExtraInfo ( mal_id ) ) || undefined ; } catch ( err ) { console . log ( err ) ; } if ( $ ! ) { if ( extraInfo ) { let broadCastDate = new Date ( ) ; let dd , mm , yyyy ; const airDay = { Lunes : 1 , Martes : 2 , Miércoles : 3 , Jueves : 4 , Viernes : 5 , Sábados : 6 , Domingos : 7 , 'Sin emisión' : 'default' , } ; if ( ! extraInfo . aired . to ) { if ( airDay . hasOwnProperty ( extraInfo . broadcast ) ) { if ( broadCastDate . getDay ( ) < airDay [ extraInfo . broadcast ] ) { for ( let i = broadCastDate . getDay ( ) ; i < airDay [ extraInfo . broadcast ] ; i ++ ) { broadCastDate . setDate ( broadCastDate . getDate ( ) + 1 ) ; } } else { let counter = broadCastDate . getDay ( ) + 1 ; broadCastDate . setDate ( broadCastDate . getDate ( ) + 1 ) ; while ( counter !== airDay [ extraInfo . broadcast ] ) { if ( counter === 7 ) { counter = 0 ; } broadCastDate . setDate ( broadCastDate . getDate ( ) + 1 ) ; counter ++ ; } } dd = broadCastDate . getDate ( ) ; mm = broadCastDate . getMonth ( ) + 1 < 10 ? `0${ broadCastDate . getMonth ( ) + 1 }` : broadCastDate . getMonth ( ) + 1 ; yyyy = broadCastDate . getFullYear ( ) ; episodesList . push ( { nextEpisodeDate : `${ yyyy }-${ mm }-${ dd }` , } ) ; } } } const scripts = $ ! ( 'script' ) . toArray ( ) ; for ( const script of scripts ) { if ( $ ! ( script ) . html ( ) ! . includes ( 'anime_info' ) ) { anime_eps = JSON . parse ( $ ! ( script ) . html ( ) ! . split ( 'var episodes = ' ) [ 1 ] . split ( ';' ) [ 0 ] ) ; } } for ( const episode of anime_eps ) { episodesList . push ( { episode : episode , id : `ver/${ id }-${ episode }` , } ) ; } if ( redisClient . connected ) { redisClient . set ( `tioanimeInfo_${ hashStringMd5 ( id ! ) }` , JSON . stringify ( episodesList ) ) ; redisClient . expireat ( `tioanimeInfo_${ hashStringMd5 ( id ! ) }` , parseInt ( `${ + new Date ( ) / 1000 }` , 10 ) + 7200 ) ; } return episodesList ; } else { return undefined ; } } ; export const videoServersMonosChinos = async ( id ) => { let $ ; let videoServers = [ ] ; try { if ( redisClient . connected ) { const resultQueryRedis = await redisClient . get ( `videoServersMonosChinos_${ hashStringMd5 ( id ) }` ) ; if ( resultQueryRedis ) { const resultRedis = JSON . parse ( resultQueryRedis ) ; return resultRedis ; } } $ = await requestGot ( `${ urls . BASE_ARUPPI_MONOSCHINOS }${ id }` , { scrapy : false , parse : true , } ) ; } catch ( err ) { return err ; } for ( const server of $ . videos ) { videoServers . push ( { id : server . title , url : server . url . replace ( "https://monoschinos2.com/reproductor?url=" , "" ) , direct : false , } ) ; } if ( videoServers . length > 0 ) { if ( redisClient . connected ) { redisClient . set ( `videoServersMonosChinos_${ hashStringMd5 ( id ) }` , JSON . stringify ( videoServers ) ) ; redisClient . expireat ( `videoServersMonosChinos_${ hashStringMd5 ( id ) }` , parseInt ( `${ + new Date ( ) / 1000 }` , 10 ) + 7200 ) ; } return videoServers ; } else { return null ; } } ; export const videoServersTioAnime = async ( id ) => { let $ ; let servers ; let videoServers = [ ] ; try { if ( redisClient . connected ) { const resultQueryRedis = await redisClient . get ( `videoServersTioAnime_${ hashStringMd5 ( id ) }` ) ; if ( resultQueryRedis ) { const resultRedis = JSON . parse ( resultQueryRedis ) ; return resultRedis ; } } $ = await requestGot ( `${ urls . BASE_TIOANIME }${ id }` , { scrapy : true , parse : false , } ) ; } catch ( err ) { return err ; } const scripts = $ ( 'script' ) . toArray ( ) ; for ( const script of scripts ) { if ( $ ( script ) . html ( ) ! . includes ( 'var videos =' ) ) { servers = JSON . parse ( $ ( script ) . html ( ) ! . split ( 'var videos = ' ) [ 1 ] . split ( ';' ) [ 0 ] ) ; } } for ( const server of servers ) { videoServers . push ( { id : server [ 0 ] . toLowerCase ( ) , url : server [ 1 ] , direct : false , } ) ; } if ( videoServers . length > 0 ) { if ( redisClient . connected ) { redisClient . set ( `videoServersTioAnime_${ hashStringMd5 ( id ) }` , JSON . stringify ( videoServers ) ) ; redisClient . expireat ( `videoServersTioAnime_${ hashStringMd5 ( id ) }` , parseInt ( `${ + new Date ( ) / 1000 }` , 10 ) + 7200 ) ; } return videoServers ; } else { return null ; } } ; export const videoServersJK = async ( id ) => { let $ ; let servers = { } ; let script = '' ; try { if ( redisClient . connected ) { const resultQueryRedis = await redisClient . get ( `videoServersJK_${ hashStringMd5 ( id ) }` ) ; if ( resultQueryRedis ) { const resultRedis = JSON . parse ( resultQueryRedis ) ; return resultRedis ; } } $ = await requestGot ( `${ urls . BASE_JKANIME }${ id }` , { scrapy : true , parse : false , } ) ; } catch ( err ) { return err ; } const serverNames = $ ( 'div.bg-servers a' ) . map ( ( index , element ) => { return $ ( element ) . text ( ) ; } ) . get ( ) ; $ ( 'script' ) . each ( ( index , element ) => { if ( $ ( element ) . html ( ) ! . includes ( 'var video = [];' ) ) { script = $ ( element ) . html ( ) ; } } ) ; try { let videoUrls = script . match ( /(?<=src=").*?(?=[\*"])/gi ) ; for ( let i = 0 ; i < serverNames . length ; i ++ ) { servers [ serverNames [ i ] ] = videoUrls ! [ i ] ; } } catch ( err ) { return null ; } let serverList = [ ] ; for ( let server in servers ) { if ( serverNames [ serverNames . indexOf ( server ) ] . toLowerCase ( ) === 'desu' ) { serverList . push ( { id : serverNames [ serverNames . indexOf ( server ) ] . toLowerCase ( ) , url : ( await desuServerUrl ( servers [ server ] ) ) !== null ? await desuServerUrl ( servers [ server ] ) : servers [ server ] , direct : false , } ) ; } else { serverList . push ( { id : serverNames [ serverNames . indexOf ( server ) ] . toLowerCase ( ) , url : servers [ server ] , direct : false , } ) ; } } serverList = serverList . filter ( x => x . id !== 'xtreme s' && x . id !== 'desuka' ) ; if ( serverList . length > 0 ) { if ( redisClient . connected ) { redisClient . set ( `videoServersJK_${ hashStringMd5 ( id ! ) }` , JSON . stringify ( serverList ) ) ; redisClient . expireat ( `videoServersJK_${ hashStringMd5 ( id ! ) }` , parseInt ( `${ + new Date ( ) / 1000 }` , 10 ) + 7200 ) ; } return serverList ; } else { return null ; } } ; async function desuServerUrl ( url ) { let $ ; try { if ( redisClient . connected ) { const resultQueryRedis = await redisClient . get ( `desuServerUrl_${ hashStringMd5 ( url ) }` ) ; if ( resultQueryRedis ) { const resultRedis = JSON . parse ( resultQueryRedis ) ; return resultRedis ; } } $ = await requestGot ( url , { scrapy : true , parse : false } ) ; } catch ( err ) { return err ; } let script = '' ; $ ( 'script' ) . each ( ( index , element ) => { if ( $ ( element ) . html ( ) ! . includes ( 'var parts = {' ) ) { if ( $ ( element ) . html ( ) ) { script = $ ( element ) . html ( ) ; } else { return null ; } } } ) ; let result = script . match ( /swarmId: '(https:\/\/\S+)'/gi ) ! . toString ( ) . split ( "'" ) [ 1 ] ; if ( result . length > 0 ) { if ( redisClient . connected ) { redisClient . set ( `desuServerUrl_${ hashStringMd5 ( url ) }` , JSON . stringify ( result ) ) ; redisClient . expireat ( `desuServerUrl_${ hashStringMd5 ( url ) }` , parseInt ( `${ + new Date ( ) / 1000 }` , 10 ) + 7200 ) ; } return result ; } else { return null ; } } export const structureThemes = async ( body , indv ) => { let themes = [ ] ; if ( indv === true ) { return { title : body . title , year : body . year , themes : await getThemesData ( body . themes ) , } ; } else { for ( let i = 0 ; i <= body . length - 1 ; i ++ ) { themes . push ( { title : body [ i ] . title , year : body [ i ] . year , themes : await getThemesData ( body [ i ] . themes ) , } ) ; } return themes ; } } ; function getThemesData ( themes ) { let items = [ ] ; for ( let i = 0 ; i <= themes . length - 1 ; i ++ ) { items . push ( { title : themes [ i ] . name . split ( '"' ) [ 1 ] || 'Remasterización' , type : themes [ i ] . type , episodes : themes [ i ] . episodes !== '' ? themes [ i ] . episodes : null , notes : themes [ i ] . notes !== '' ? themes [ i ] . notes : null , video : themes [ i ] . link , } ) ; } return items . filter ( x => x . title !== 'Remasterización' ) ; } export function getThemes ( themes ) { return themes . map ( ( item ) => ( { name : item . themeName , title : item . themeType , link : item . mirror . mirrorURL , } ) ) ; } export const imageUrlToBase64 = async ( url ) => { let img = await requestGot ( url ) ; return img . rawBody . toString ( 'base64' ) ; } ; export function hashStringMd5 ( string ) { return crypto . createHash ( 'md5' ) . update ( string ) . digest ( 'hex' ) ; }