You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

262 lines
9.4 KiB

const {parse} = require('node-html-parser');
const {decodeHTML} = require('../lib')
module.exports = class AsuraModule
{
/**
* @property {Scanlator} scanlator - Scanlator name
* @typedef {String} Scanlator
* @pattern /^[\w-]+-scans$/
*/
constructor()
{
this.scanlator = 'Asura-scans'
this.BaseLink = 'https://asuratoon.com/'
this.timeout = 5000;
}
/**
*
* @param {String} query
* @returns {Array<Manga>}
* @typedef {Object} Manga
* @property {Link} link - Manga Link
* @property {String} title - Manga Title
* @property {Link} img - Image Link
* @property {Number} latestChap - Latest Chapter Number
* @typedef {String} Link
*/
async Search(query)
{
return await fetch(this.BaseLink+'?s='+query, {timeout:this.timeout})
.then(handleResponse)
.then(handleData)
.catch(handleError);
function handleResponse(response)
{
return response.text();
}
function handleError(error)
{
return error;
}
function handleData(data)
{
data = data.split('<div class="listupd">')[1].split('<div class="pagination">')[0]
const document = parse(data);
var payload = [];
for(var result of document.querySelectorAll('.bs > .bsx > a'))
{
var aux = {
link:result.rawAttrs.split('"')[1],
title:result.rawAttrs.split('"')[3],
img:'https://'+result.querySelectorAll('img')[0].rawAttrs.split('"')[1].split('https://')[2],
status: result.querySelector('.status')?.rawText || 'Ongoing',
latestChap:parseInt(result.querySelector('.epxs').innerText.split(' ')[1]),
};
payload.push(aux);
}
return payload
}
}
/**
*
* @param {String} query
* @returns {Array<Manga>}
* @typedef {Object} Manga
* @property {Link} link - Manga Link
* @property {String} title - Manga Title
* @property {Link} img - Image Link
* @property {Number} latestChap - Latest Chapter Number
* @typedef {String} Link
*/
async SearchByTag(query, ammount=5)
{
return await fetch(this.BaseLink+'/genres/'+query, {timeout:this.timeout})
.then(handleResponse)
.then(handleData)
.catch(handleError);
function handleResponse(response)
{
return response.text();
}
function handleError(error)
{
return error;
}
function handleData(data)
{
data = data.split('<div class="listupd">')[1].split('<div class="pagination">')[0]
const document = parse(data);
var payload = [];
var results = document.querySelectorAll('a')
var limit = results.length<ammount?results.length:ammount;
for(var i =0;i<limit; i++)
{
const result = results[i];
var aux = {
link:result.rawAttrs.split('"')[1],
title:decodeHTML(result.rawAttrs.split('"')[3]),
img:result.querySelectorAll('.limit > img')[0].rawAttrs.split('src="')[1].split(')/')[1].split('"')[0],
status:result.querySelector('.status')?.rawText||'Ongoing',
latestChap:parseInt(result.querySelectorAll('.epxs')[0].innerText.split(' ')[1]),
};
payload.push(aux);
}
return payload
}
}
/**
*
* @param {String} name Manga/Manwha Name
* @param {Link} link Manga url (
* @returns {Array<Chapter>} - Chapters Array
* @typedef {Object} Chapter
* @property {Number} num - Chapter Number (Float)
* @property {String} link - Chapter Link
* @property {String} date - Chapter Release Date
* @typedef {String} Link
* @pattern ^(https?:\/\/)?([\w\d.-]+)\.([a-z]{2,})(:[0-9]+)?(\/\S*)?$
*/
async ChapterList(link, name)
{
return await fetch(link, {timeout:this.timeout})
.then(handleResponse)
.then(handleData)
.catch(handleError);
function handleResponse(response)
{
return response.text();
}
function handleError(error)
{
return error;
}
function handleData(data)
{
const document = parse(data);
const chapterlist = document.querySelectorAll('ul')[1];
const chapters = chapterlist.querySelectorAll('li');
var payload = [];
try {
for(var chapter of chapters)
{
var aux = {
num:parseFloat(chapter.rawAttrs.split('"')[1]),
link:chapter.querySelector('.eph-num').innerHTML.split('"')[1],
date:chapter.querySelector('.chapterdate').innerText
};
payload.push(aux);
}
} catch (error) {
throw new Error('This manga should be called by url', error);
}
return payload
}
}
/**
*
* @param {Link} Link Chapter Link
* @returns {ChapterList}
* @typedef {Obejct} ChapterList
* @property {Array<Image>} List
* @property {Link} mangaLink - Manga Link
* @typedef {String} Image - Image link
* @typedef {String} Link
* @pattern ^(https?:\/\/)?([\w\d.-]+)\.([a-z]{2,})(:[0-9]+)?(\/\S*)?$
*/
async Chapter(Link)
{
return await fetch(Link, {timeout:this.timeout})
.then(handleResponse)
.then(handleData)
.catch(handleError);
function handleResponse(response)
{
return response.text();
}
function handleError(error)
{
return error;
}
function handleData(data)
{
const document = parse(data);
let List = [];
let mangaLink = document.querySelectorAll('.allc')[0].querySelector('a')._rawAttrs.href;
for(var image of document.getElementById('readerarea').querySelectorAll('img'))
{
if(image.rawAttrs)
{
let index = image.rawAttrs.split('"').findIndex(el => el.includes('http'));
List.push(image.rawAttrs.split('"')[index].replace(/\n/g, ''));
}
}
return {List, mangaLink}
}
}
/**
*
* @param {String} Title
* @returns {Manga}
* @typedef {Object} Manga
* @property {Link} Link - Manga Link
* @property {Link} img - Image Link
* @property {String} description - Latest Chapter Number
* @property {String} Type - Manga Type
* @property {String} Released - Year of Release
* @property {String} Author - Author's name
* @property {String} Artist - Artist Team
* @property {String} Serialization - Serialization Company
* @property {Number} latestChap - Latest Chap number
* @property {Array<String>} tags - Manga Tags
* @typedef {String} Link
*/
async GetManga(Link, title)
{
const auxTitle = title;
return await fetch(Link, {timeout:this.timeout})
.then(handleResponse)
.then(handleData)
.catch(handleError);
function handleResponse(response)
{
return response.text();
}
function handleError(error)
{
return error;
}
function handleData(data)
{
const parsed = parse(data)
let description = [];
parsed.querySelectorAll('.entry-content-single')[0].querySelectorAll('p').forEach(p=>description.push(p.innerText));
description = decodeHTML(description.join(' '));
const img = 'https://'+parsed.querySelectorAll('img')[1].rawAttrs.split('src="')[1].split('https://')[2].split('"')[0];
let tags = parsed.querySelectorAll('.mgen')[0].structuredText.split('\n')[0].split(' ');
let latestChap = parseInt(parsed.querySelectorAll('.epcurlast')[0].rawText.split(' ')[1])
let table = parsed.querySelectorAll('.infox')[0].querySelectorAll('.fmed');
table.splice(-3);
const aux = {};
for (let i = 0; i < table.length; i++) {
const key = decodeHTML(table[i].querySelector('b').innerText);
aux[key] = decodeHTML(table[i].querySelector('span').innerText);
}
aux['Status'] = parsed.querySelectorAll('.imptdt')[0].innerText.split('\n')[1].split(' ')[1];
aux['Type'] = parsed.querySelectorAll('.imptdt')[1].innerText.split('\n')[1].split(' ')[1];
return {description, img, ...aux, tags, title:auxTitle, latestChap, link:Link}
}
}
async hasTitle(title)
{
const Search = await this.Search(title);
if(!Array.isArray(Search)) return false
return Search.filter(Manga => {return Manga.title === title})[0];
}
}