import chalk from "chalk" ; import fetch from "node-fetch-extra" ; import { JSDOM } from "jsdom" ; import { error } from "./index" ; import { Chapter , ScraperError , ScraperResponse } from "../types" ; import { Scraper , SearchOptions } from "./types" ; import { getProviderId , isProviderId } from "../routers/manga-page" ; import updateManga from "../util/updateManga" ; export class mangahereClass extends Scraper { constructor ( ) { super ( ) ; this . provider = "Mangahere" ; this . canSearch = true ; this . nsfw = false ; } public async search ( query , options ? ) { const { resultCount } = { resultCount : 12 , ... options } ; let pageUrl ; if ( query === "" ) { pageUrl = "http://www.mangahere.cc/ranking/" ; } else { pageUrl = `http://www.mangahere.cc/search?title=${ encodeURIComponent ( query ) }` ; } const pageReq = await fetch ( pageUrl ) ; const pageHtml = await pageReq . text ( ) ; const dom = new JSDOM ( pageHtml ) ; const document = dom . window . document ; const anchors = [ ... document . querySelectorAll ( "p.manga-list-4-item-title a" ) , ... document . querySelectorAll ( "p.manga-list-1-item-title a" ) , ] ; const ids = anchors . map ( ( anchor ) => anchor . href . split ( "/" ) [ 2 ] ) . slice ( 0 , resultCount ) ; const searchResultData = await Promise . all ( ids . map ( ( id ) => updateManga ( "mangahere" , id ) ) ) ; return searchResultData ; } /**
     * The scrape function
     */ public async scrape ( slug , chapterId ) { const maxTimeout = new Promise ( ( resolve ) => { setTimeout ( ( ) => { resolve ( error ( 0 , "This request took too long" ) ) ; } , 25e3 ) ; } ) ; const scraping = this . doScrape ( slug , chapterId ) ; const raceResult = await Promise . race ( [ maxTimeout , scraping ] ) ; if ( raceResult . success === false && raceResult . err === "This request took too long" ) { console . error ( chalk . red ( "[mangahere]" ) + ` A request for '${ slug }' at '${ chapterId }' took too long and has timed out` ) ; } return raceResult ; } private async doScrape ( slug , chapterId ) { const pageReq = await fetch ( `http://www.mangahere.cc/manga/${ slug }` , { headers : { cookie : "isAdult=1" } } ) ; const pageHtml = await pageReq . text ( ) ; const dom = new JSDOM ( pageHtml ) ; const document = dom . window . document ; const title = document . querySelector ( ".detail-info-right-title-font" ) . textContent ; let posterUrl = document . querySelector ( ".detail-info-cover-img" ) . src ; if ( posterUrl . startsWith ( "/" ) ) posterUrl = "https://www.mangahere.cc" + posterUrl ; posterUrl = `/proxy-image?url=${ posterUrl }` ; const genreWrapper = document . querySelector ( ".detail-info-right-tag-list" ) ; const genreLinks = [ ... genreWrapper . querySelectorAll ( "a" ) ] ; const genres = genreLinks . map ( ( v ) => v . textContent ) ; const alternateTitles = [ "" ] ; const statusWrapper = document . querySelector ( ".detail-info-right-title-tip" ) ; const status = statusWrapper . textContent . toLowerCase ( ) ; const chapters = [ ... document . querySelectorAll ( ".detail-main-list li" ) , ] . reverse ( ) . map ( ( row ) : Chapter => { const label = row . querySelector ( "a .detail-main-list-main .title3" ) . textContent ; const slug = row . querySelector ( "a" ) . href . split ( "/" ) [ 3 ] ; const chapter = row . querySelector ( "a" ) . href . split ( "/" ) [ 3 ] . slice ( 1 ) ; let date = new Date ( row . querySelector ( "a .detail-main-list-main .title2" ) . textContent ) ; if ( ! date . getTime ( ) ) date = new Date ( ) ; return { label , hrefString : slug , season : 1 , chapter , date , combined : Number ( chapter ) } ; } ) ; let chapterImages = [ ] ; if ( chapterId != "-1" ) { const url = `http://m.mangahere.cc/roll_manga/${ slug }/${ chapterId }/1.html` ; const chapterPageReq = await fetch ( url ) ; const chapterPageHtml = await chapterPageReq . text ( ) ; const dom = new JSDOM ( chapterPageHtml ) ; const chapterDocument = dom . window . document ; const images = [ ... chapterDocument . querySelectorAll ( ".mangaread-img img" ) , ] ; chapterImages = images . map ( ( v ) => "http:" + v . getAttribute ( "data-original" ) ) ; } const descriptionParagraphs = document . querySelector ( ".fullcontent" ) . textContent . split ( /\n|<br>/g ) ; const providerId = getProviderId ( this . provider ) ; return { constant : { title , slug , posterUrl , alternateTitles , descriptionParagraphs , genres , nsfw : false } , data : { chapters , chapterImages , status } , success : true , provider : isProviderId ( providerId ) ? providerId : null } ; } } const mangahere = new mangahereClass ( ) ; export default mangahere ;