manga-parser
Version:
A parser for manga online sources
352 lines (282 loc) • 9.11 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
var _lodash = require('lodash');
var _lodash2 = _interopRequireDefault(_lodash);
var _bluebird = require('bluebird');
var _bluebird2 = _interopRequireDefault(_bluebird);
var _cheerio = require('cheerio');
var _cheerio2 = _interopRequireDefault(_cheerio);
var _sites = require('./sites');
var catalogs = _interopRequireWildcard(_sites);
var _chapterRecognition = require('./chapter-recognition');
var _chapterRecognition2 = _interopRequireDefault(_chapterRecognition);
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
let request = require('request');
request = request.defaults({
timeout: 20000,
gzip: true
});
class Parser {
constructor() {
let sources = {};
_lodash2.default.forEach(catalogs, catalog => {
sources[catalog.catalogName] = catalog;
});
this.catalogs = sources;
}
/**
* Fetch the popular mangas on the catalog
* @param {string} catalogName
* @param {number} page Page to fetch
* @returns {Promise<{mangas: Array<Manga>, hasNext: boolean, nextUrl: string, nextPage: number}>}
*/
getPopularMangaList(catalogName, page = null) {
const catalog = this.getCatalog(catalogName);
let options = catalog.popularMangaRequest(page);
return new _bluebird2.default(function (resolve, reject) {
request(options, function (error, response, page) {
if (error) {
return reject(error);
}
let $ = _cheerio2.default.load(page);
let mangas;
let paginator;
try {
mangas = catalog.popularMangaList($);
} catch (error) {
return reject(error);
}
try {
paginator = catalog.popularMangaPaginator($);
} catch (error) {
return reject(error);
}
return resolve(_extends({
mangas
}, paginator));
});
});
}
/**
* Fetch the latest updated manga on the catalog
* @param {string} catalogName
* @param {number} page Page to fetch
* @returns {Promise<{mangas: Array<Manga>, hasNext: boolean, nextUrl: string, nextPage: number}>}
*/
getLatestUpdatesList(catalogName, page = null) {
const catalog = this.getCatalog(catalogName);
let options = catalog.latestUpdatesRequest(page);
return new _bluebird2.default(function (resolve, reject) {
request(options, function (error, response, page) {
if (error) {
return reject(error);
}
let $ = _cheerio2.default.load(page);
let mangas;
let paginator;
try {
mangas = catalog.latestUpdatesList($);
} catch (error) {
return reject(error);
}
try {
paginator = catalog.latestUpdatesPaginator($);
} catch (error) {
return reject(error);
}
return resolve(_extends({
mangas
}, paginator));
});
});
}
/**
* Search for Manga from a catalog
* @param {string} catalogName
* @param {string} query
* @param {?number} page
* @returns {Promise<{ mangas: Array<Manga>, hasNext: boolean, nextUrl: ?string, nextPage: ?number }>}
*/
searchManga(catalogName, query, page = null) {
const catalog = this.getCatalog(catalogName);
const options = catalog.searchOptions(query, page);
return new _bluebird2.default(function (resolve, reject) {
request(options, function (error, response, page) {
if (error) {
return reject(error);
}
let $ = _cheerio2.default.load(page);
let mangas;
let paginator;
try {
mangas = catalog.search($);
} catch (error) {
return reject(error);
}
try {
paginator = catalog.searchPaginator($);
} catch (error) {
return reject(error);
}
return resolve(_extends({
mangas
}, paginator));
});
});
}
/**
* Fetch every information for a Manga
* @param {string} catalogName
* @param {Manga} manga
* @returns {Promise<Manga>}
*/
getMangaDetail(catalogName, manga) {
const catalog = this.getCatalog(catalogName);
return new _bluebird2.default(function (resolve, reject) {
request(manga.url, function (error, response, page) {
if (error) {
return reject(error);
}
let $ = _cheerio2.default.load(page);
try {
manga = catalog.mangaDetail($, manga);
} catch (error) {
return reject(error);
}
resolve(manga);
});
});
}
/**
* Fetch the list of chapters for Manga
* @param {string} catalogName
* @param {Manga} manga
* @returns {Promise<Array<Chapter>>}
*/
getChapterList(catalogName, manga) {
const catalog = this.getCatalog(catalogName);
return new _bluebird2.default(function (resolve, reject) {
request(manga.url, function (error, response, page) {
if (error) {
return reject(error);
}
let $ = _cheerio2.default.load(page);
let chapters;
try {
chapters = catalog.chapterList($);
} catch (error) {
return reject(error);
}
_lodash2.default.forEach(chapters, (chapter, index) => {
chapters[index] = _chapterRecognition2.default.parseChapterNumber(chapter, manga);
});
chapters = _lodash2.default.orderBy(chapters, ['number', 'publishedAt'], ['asc', 'asc']);
resolve(chapters);
});
});
}
/**
* Fetch the list of chapters for a Manga sorted by volumes
* @param {string} catalogName
* @param {Manga} manga
* @returns {Promise<{}>}
*/
getChapterListByVolumes(catalogName, manga) {
const catalog = this.getCatalog(catalogName);
if (!catalog.hasVolumeInfos) {
return _bluebird2.default.reject(`${catalogName} does not have volume infos`);
}
return new _bluebird2.default(function (resolve, reject) {
request(manga.url, function (error, response, page) {
if (error) {
return reject(error);
}
let $ = _cheerio2.default.load(page);
let volumes;
try {
volumes = catalog.chapterListByVolume($);
} catch (error) {
return reject(error);
}
_lodash2.default.forEach(volumes, (chapters, volume) => {
_lodash2.default.forEach(chapters, (chapter, index) => {
chapters[index] = _chapterRecognition2.default.parseChapterNumber(chapter, manga);
});
volumes[volume] = _lodash2.default.orderBy(chapters, ['number', 'publishedAt'], ['asc', 'asc']);
});
resolve(volumes);
});
});
}
/**
* Fetch every pages URL for a manga
* @param {string} catalogName
* @param {Chapter} chapter
* @returns {Promise<Array<string>>}
*/
getPageList(catalogName, chapter) {
const catalog = this.getCatalog(catalogName);
return new _bluebird2.default((resolve, reject) => {
request(chapter.url, (error, response, page) => {
if (error) {
return reject(error);
}
let $ = _cheerio2.default.load(page);
let pages;
try {
pages = catalog.pageList($);
} catch (error) {
return reject(error);
}
return resolve(pages);
});
});
}
/**
* Fetch the image URL from a page URL
* @param {string} catalogName
* @param {string} pageURL
* @returns {Promise<string>}
*/
getImageURL(catalogName, pageURL) {
const catalog = this.getCatalog(catalogName);
return new _bluebird2.default((resolve, reject) => {
request(pageURL, (error, response, page) => {
if (error) {
return reject(error);
}
let $ = _cheerio2.default.load(page);
let imageURL;
try {
imageURL = catalog.imageUrl($);
} catch (error) {
return reject(error);
}
return resolve(imageURL);
});
});
}
/**
* Return the list of catalogs
* @returns {{name:AbstractCatalog}}
*/
getCatalogs() {
return this.catalogs;
}
/**
* Return a catalog
* @param {string} catalogName
* @returns {AbstractCatalog}
*/
getCatalog(catalogName) {
if (!(catalogName in this.catalogs)) {
throw new Error('Catalog does not exist');
}
return this.catalogs[catalogName];
}
}
exports.default = new Parser();