123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218 |
- const path = require('path');
- const _ = require('lodash');
- const he = require('he');
- const dayjs = require('dayjs');
- const BasePage = require('./BasePage');
- const Fb2Parser = require('../fb2/Fb2Parser');
- class BookPage extends BasePage {
- constructor(config) {
- super(config);
- this.id = 'book';
- this.title = 'Книга';
- }
- formatSize(size) {
- size = size/1024;
- let unit = 'KB';
- if (size > 1024) {
- size = size/1024;
- unit = 'MB';
- }
- return `${size.toFixed(1)} ${unit}`;
- }
- inpxInfo(bookRec) {
- const mapping = [
- {name: 'fileInfo', label: 'Информация о файле', value: [
- {name: 'folder', label: 'Папка'},
- {name: 'file', label: 'Файл'},
- {name: 'size', label: 'Размер'},
- {name: 'date', label: 'Добавлен'},
- {name: 'del', label: 'Удален'},
- {name: 'libid', label: 'LibId'},
- {name: 'insno', label: 'InsideNo'},
- ]},
- {name: 'titleInfo', label: 'Общая информация', value: [
- {name: 'author', label: 'Автор(ы)'},
- {name: 'title', label: 'Название'},
- {name: 'series', label: 'Серия'},
- {name: 'genre', label: 'Жанр'},
- {name: 'librate', label: 'Оценка'},
- {name: 'lang', label: 'Язык книги'},
- {name: 'keywords', label: 'Ключевые слова'},
- ]},
- ];
- const valueToString = (value, nodePath, b) => {//eslint-disable-line no-unused-vars
- if (nodePath == 'fileInfo/file')
- return `${value}.${b.ext}`;
- if (nodePath == 'fileInfo/size')
- return `${this.formatSize(value)} (${value.toString().replace(/(\d)(?=(\d{3})+(?!\d))/g, '$1 ')} Bytes)`;
- if (nodePath == 'fileInfo/date')
- return dayjs(value, 'YYYY-MM-DD').format('DD.MM.YYYY');
- if (nodePath == 'fileInfo/del')
- return (value ? 'Да' : null);
- if (nodePath == 'fileInfo/insno')
- return (value ? value : null);
- if (nodePath == 'titleInfo/author')
- return value.split(',').join(', ');
- if (nodePath == 'titleInfo/librate' && !value)
- return null;
- if (typeof(value) === 'string') {
- return value;
- }
- return (value.toString ? value.toString() : '');
- };
- let result = [];
- const book = _.cloneDeep(bookRec);
- book.series = [book.series, book.serno].filter(v => v).join(' #');
- for (const item of mapping) {
- const itemOut = {name: item.name, label: item.label, value: []};
- for (const subItem of item.value) {
- const subItemOut = {
- name: subItem.name,
- label: subItem.label,
- value: valueToString(book[subItem.name], `${item.name}/${subItem.name}`, book)
- };
- if (subItemOut.value)
- itemOut.value.push(subItemOut);
- }
- if (itemOut.value.length)
- result.push(itemOut);
- }
- return result;
- }
- htmlInfo(title, infoList) {
- let info = '';
- for (const part of infoList) {
- if (part.value.length)
- info += `<h3>${part.label}</h3>`;
- for (const rec of part.value)
- info += `<p>${rec.label}: ${rec.value}</p>`;
- }
- if (info)
- info = `<h2>${title}</h2>${info}`;
- return info;
- }
- async body(req) {
- const result = {};
- result.link = this.baseLinks(req, true);
- const bookUid = req.query.uid;
- const entry = [];
- if (bookUid) {
- const {bookInfo} = await this.webWorker.getBookInfo(bookUid);
- if (bookInfo) {
- const {genreMap} = await this.getGenres();
- //format
- const ext = bookInfo.book.ext;
- let fileFormat = `${ext}+zip`;
- let downHref = bookInfo.link;
- if (ext === 'mobi') {
- fileFormat = 'x-mobipocket-ebook';
- } else if (ext == 'epub') {
- //
- } else {
- downHref = `${bookInfo.link}/zip`;
- }
- //entry
- const e = this.makeEntry({
- id: bookUid,
- title: bookInfo.book.title || 'Без названия',
- });
- e['dc:language'] = bookInfo.book.lang;
- e['dc:format'] = fileFormat;
- //genre
- const genre = bookInfo.book.genre.split(',');
- for (const g of genre) {
- const genreName = genreMap.get(g);
- if (genreName) {
- if (!e.category)
- e.category = [];
- e.category.push({
- '*ATTRS': {term: genreName, label: genreName},
- });
- }
- }
- let content = '';
- let ann = '';
- let info = '';
- //fb2 info
- if (bookInfo.fb2) {
- const parser = new Fb2Parser(bookInfo.fb2);
- const infoObj = parser.bookInfo();
- if (infoObj.titleInfo) {
- if (infoObj.titleInfo.author.length) {
- e.author = infoObj.titleInfo.author.map(a => ({name: a}));
- }
- ann = infoObj.titleInfo.annotationHtml || '';
- const infoList = parser.bookInfoList(infoObj);
- info += this.htmlInfo('Fb2 инфо', infoList);
- }
- }
- //content
- info += this.htmlInfo('Inpx инфо', this.inpxInfo(bookInfo.book));
- content = `${ann}${info}`;
- if (content) {
- e.content = {
- '*ATTRS': {type: 'text/html'},
- '*TEXT': he.escape(content),
- };
- }
- //links
- e.link = [ this.downLink({href: downHref, type: `application/${fileFormat}`}) ];
- if (bookInfo.cover) {
- let coverType = 'image/jpeg';
- if (path.extname(bookInfo.cover) == '.png')
- coverType = 'image/png';
- e.link.push(this.imgLink({href: bookInfo.cover, type: coverType}));
- e.link.push(this.imgLink({href: bookInfo.cover, type: coverType, thumb: true}));
- }
- entry.push(e);
- }
- }
- result.entry = entry;
- return this.makeBody(result, req);
- }
- }
- module.exports = BookPage;
|