import fetch from "node-fetch-extra" ; import chalk from "chalk" ; import updateManga from "../util/updateManga" ; import { XmlEntities } from "html-entities" ; import { Chapter , ScraperError , ScraperResponse } from "../types" ; import { Scraper , SearchOptions } from "./types" ; import { getProviderId , isProviderId } from "../routers/manga-page" ; import { error } from "./index" ; const Entities = new XmlEntities ( ) ; class RCOClass extends Scraper { constructor ( ) { super ( ) ; this . provider = "RCO" ; this . canSearch = true ; this . nsfw = false ; } public async scrape ( slug , chapterId = null ) { const maxTimeout = new Promise ( ( resolve ) => { setTimeout ( ( ) => { resolve ( error ( 0 , "This request took too long" ) ) ; } , 10e3 ) ; } ) ; 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 ( "[RCO]" ) + ` A request for '${ slug }' at '${ chapterId }' took too long and has timed out` ) ; } return raceResult ; } private async doScrape ( slug , chapterId = - 1 ) { try { const mainReq = await fetch ( `https://readcomiconline.li/Comic/${ slug }` , { family : 6 , headers : { "user-agent" : "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.80 Safari/537.36" } } ) ; let html = await mainReq . text ( ) ; html = html . replace ( /\r\n| {2}|\t/g , "" ) ; const title = Entities . decode ( html . split ( '<a Class="bigChar"' ) [ 1 ] . split ( ">" ) [ 1 ] . split ( "</" ) [ 0 ] ) ; let posterUrl = "/poster.png" ; try { posterUrl = html . split ( "Cover</div>" ) [ 1 ] . trim ( ) . split ( 'src="' ) [ 1 ] . split ( '"' ) [ 0 ] . replace ( /https\/\//g , "https://" ) ; if ( ! posterUrl . startsWith ( "http" ) ) posterUrl = "https://readcomiconline.li" + posterUrl ; } catch ( err ) { posterUrl = "/poster.png" ; } let descriptionParagraphs = [ ] ; try { descriptionParagraphs = Entities . decode ( html . split ( '<p style="text-align: justify;">' ) [ 1 ] . split ( "</p>" ) [ 0 ] ) . split ( "<br />" ) ; } catch ( err ) { } const chaptersHTML = html . split ( "<tr>" ) . slice ( 2 ) . map ( ( s ) => s . split ( "</tr>" ) [ 0 ] ) ; const chapters = chaptersHTML . map ( ( str , i ) => { const tds = str . split ( "<td>" ) . map ( ( s ) => s . split ( "</td>" ) [ 0 ] ) ; const tdOne = tds [ 1 ] ; const tdTwo = tds [ 2 ] ; const label = tdOne . split ( '">' ) [ 1 ] . split ( "</" ) [ 0 ] . replace ( title , "" ) . trim ( ) ; const hrefString = tdOne . split ( 'href="' ) [ 1 ] . split ( '"' ) [ 0 ] . split ( "?" ) [ 0 ] . split ( "/" ) . pop ( ) ; return { label , season : 1 , chapter : chaptersHTML . length - i , combined : chaptersHTML . length - i , date : new Date ( tdTwo ) , hrefString } ; } ) . sort ( ( a , b ) => a . combined - b . combined ) ; let chapterImages = [ ] ; if ( chapterId !== - 1 ) { const imgReq = await fetch ( `https://readcomiconline.li/Comic/${ slug }/${ chapterId }?quality=lq` , { family : 6 , headers : { "user-agent" : "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.80 Safari/537.36" } } ) ; const chapterHTML = await imgReq . text ( ) ; const js = chapterHTML . split ( "var lstImages = new Array();" ) [ 1 ] . split ( "var currImage = 0;" ) [ 0 ] ; const imgSources = js . match ( /lstImages\.push\("(.+?)"\);/g ) . map ( ( snippet ) => { return snippet . match ( /lstImages\.push\("(.+?)"\);/ ) [ 1 ] ; } ) ; chapterImages = imgSources ; } const status = html . split ( "Status:</span>" ) [ 1 ] . split ( "<" ) [ 0 ] . trim ( ) . replace ( /&nbsp;/g , "" ) . toLowerCase ( ) ; const provider = getProviderId ( this . provider ) ; return { constant : { title , slug , posterUrl , alternateTitles : [ ] , genres : [ ] , descriptionParagraphs , nsfw : false } , data : { chapters , chapterImages , status } , success : true , provider : isProviderId ( provider ) ? provider : null } ; } catch ( err ) { console . error ( chalk . red ( "[RCO]" ) + " An error occured:" , err ) ; return error ( 0 , err ) ; } } public async search ( query , options ? ) { if ( ! this . canSearch ) { return { error : "Unable to search. Check logs for more information." } ; } let resultIds = [ ] ; if ( query === "" ) { const mainReq = await fetch ( "https://readcomiconline.li/ComicList/MostPopular" , { family : 6 , headers : { "user-agent" : "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.80 Safari/537.36" } } ) ; const body = await mainReq . text ( ) ; const divs = body . split ( "<tr>" ) . slice ( 1 ) . map ( ( v ) => v . split ( "</tr>" ) [ 0 ] . replace ( /\r\n| {2}|\t/g , "" ) ) ; resultIds = divs . map ( ( div ) => { const slug = div . split ( 'href="/Comic/' ) [ 1 ] . split ( '"' ) [ 0 ] ; return slug ; } ) ; } else { const searchUrl = "https://readcomiconline.li/Search/Comic" ; const searchReq = await fetch ( searchUrl , { family : 6 , method : "POST" , headers : { "content-type" : "application/x-www-form-urlencoded" , "user-agent" : "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.80 Safari/537.36" } , body : `keyword=${ query . split ( " " ) . join ( "+" ) }` } ) ; if ( searchReq . url === searchUrl ) { const searchHTML = await searchReq . text ( ) ; resultIds = searchHTML . split ( '<a href="/Comic/' ) . slice ( 1 ) . map ( ( v ) => v . split ( '"' ) [ 0 ] ) ; } else { resultIds = [ searchReq . url . split ( "/" ) . pop ( ) ] ; } } const chapterCount = query === "" ? 15 : options . resultCount ; const searchResults = await Promise . all ( resultIds . slice ( 0 , chapterCount ) . map ( ( id ) => updateManga ( "RCO" , id . toString ( ) ) ) ) ; return searchResults . filter ( ( r ) => r . success ) ; } } const RCOInstance = new RCOClass ( ) ; export default RCOInstance ;