flibusta-api
Version:
> **Disclaimer**: This package is only created as an example of a search tool for Flibusta. If you like to read books - buy them legally.
115 lines (114 loc) • 4.13 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.searchBooks = searchBooks;
exports.searchByAuthor = searchByAuthor;
exports.getBookInfo = getBookInfo;
exports.downBook = downBook;
exports.getUrl = getUrl;
const axios_1 = require("axios");
const logger_1 = require("./logger");
const cheerio = require("cheerio");
const html_to_text_1 = require("html-to-text");
const ORIGIN = 'http://flibusta.is';
async function getPage(url) {
try {
const { data } = await axios_1.default.get(url);
return data;
}
catch (error) {
logger_1.logger.log(error);
}
}
const compiledConvert = (0, html_to_text_1.compile)({ decodeEntities: true, selectors: [{ selector: 'a', options: { ignoreHref: true } }] });
async function searchBooks(text, limit = 20) {
const page = await getPage(`${ORIGIN}/booksearch?ask=${encodeURIComponent(text)}&chb=on`);
const bookSearchString = /<a href="(\/b\/)(?<id>[0-9]*)">(?<title>.*)<\/a> - (?<author>.*)/gi;
const results = [];
let match;
while ((match = bookSearchString.exec(page))) {
if (match && match.groups) {
const { id, title, author } = match.groups;
results.push({
id: parseInt(id),
title: compiledConvert(title),
author: compiledConvert(author),
link: `/download_${id}`,
sendLink: `/send_${id}`,
});
}
}
return results.slice(0, limit);
}
async function searchByAuthor(text, limit = 10) {
const SEARCH_URL = `${ORIGIN}/booksearch?ask=${encodeURIComponent(text)}&cha=on`;
const page = await getPage(SEARCH_URL);
const re = /<li><a href="(\/a\/)(?<id>[0-9]*)">(?<name>.*)<\/a>/gi;
const results = [];
const ids = [];
let match;
while ((match = re.exec(String(page)))) {
if (match && match.groups) {
const { id, name } = match.groups;
ids.push({ id, name });
}
}
if (ids.length === 0)
return [];
const [author] = ids;
const authorPage = await getPage(`${ORIGIN}/a/${author.id}`);
const reBook = /<a href="(\/b\/)(?<id>[0-9]*)">(?<title>[\s\S]*?)<\/a>/gi;
while ((match = reBook.exec(String(authorPage)))) {
if (match && match.groups) {
const { id, title } = match.groups;
results.push({
id: parseInt(id),
title: compiledConvert(title),
author: compiledConvert(author.name),
link: `/download_${id}`,
sendLink: `/send_${id}`,
});
}
}
return limit ? results.slice(0, limit) : results;
}
async function getBookInfo(id) {
const page = await getPage(`${ORIGIN}/b/${id}`);
const $ = await cheerio.load(page);
try {
const bookInfo = { id };
const author = $('#main > a[href^="/a/"]').first().text().trim();
const title = $('#main > .title').text().trim();
const description = $('#main > h2 + p').text().trim();
const genres = $('#main > div > p > a[href^="/g/"]').toArray();
bookInfo.author = author || '';
bookInfo.title = title || '';
bookInfo.description = description || '';
bookInfo.genres = (genres === null || genres === void 0 ? void 0 : genres.map((e) => ({
id: e.attribs['name'],
title: $(e).text().trim(),
}))) || [];
return bookInfo;
}
catch (e) {
logger_1.logger.error(e);
}
}
async function downBook(id, format = 'mobi') {
var _a;
const response = await (0, axios_1.default)({
url: getUrl(id, format),
method: 'GET',
responseType: 'stream',
});
const fileName = (_a = response === null || response === void 0 ? void 0 : response.headers['content-disposition']) === null || _a === void 0 ? void 0 : _a.slice(21);
if (!fileName)
throw new Error(`Book ${id} unavailable.`);
return {
id,
file: response.data,
fileName,
};
}
function getUrl(id, format = 'mobi') {
return `${ORIGIN}/b/${id}/${format}`;
}