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 += `

${part.label}

`; for (const rec of part.value) info += `

${rec.label}: ${rec.value}

`; } if (info) info = `

${title}

${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;