UNPKG

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
"use strict"; 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}`; }