Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ed5dc25d94 | ||
|
|
dd11e8c5ad | ||
|
|
2db2b8cff4 | ||
|
|
4d3661b758 | ||
|
|
891b1e4fe8 | ||
|
|
d588b16885 |
@@ -231,12 +231,12 @@ class Api {
|
|||||||
return await this.request({action: 'get-genre-tree'});
|
return await this.request({action: 'get-genre-tree'});
|
||||||
}
|
}
|
||||||
|
|
||||||
async getBookLink(bookId) {
|
async getBookLink(bookUid) {
|
||||||
return await this.request({action: 'get-book-link', bookId}, 120);
|
return await this.request({action: 'get-book-link', bookUid}, 120);
|
||||||
}
|
}
|
||||||
|
|
||||||
async getBookInfo(bookId) {
|
async getBookInfo(bookUid) {
|
||||||
return await this.request({action: 'get-book-info', bookId}, 120);
|
return await this.request({action: 'get-book-info', bookUid}, 120);
|
||||||
}
|
}
|
||||||
|
|
||||||
async getConfig() {
|
async getConfig() {
|
||||||
|
|||||||
@@ -238,6 +238,13 @@ class AuthorList extends BaseList {
|
|||||||
const booksToFilter = await this.loadAuthorBooks(item.key);
|
const booksToFilter = await this.loadAuthorBooks(item.key);
|
||||||
const filtered = this.filterBooks(booksToFilter);
|
const filtered = this.filterBooks(booksToFilter);
|
||||||
|
|
||||||
|
if (!filtered.length && this.list.totalFound == 1) {
|
||||||
|
this.list.queryFound = 0;
|
||||||
|
this.list.totalFound = 0;
|
||||||
|
this.searchResult.found = [];
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
const prepareBook = (book) => {
|
const prepareBook = (book) => {
|
||||||
return Object.assign(
|
return Object.assign(
|
||||||
{
|
{
|
||||||
@@ -345,7 +352,10 @@ class AuthorList extends BaseList {
|
|||||||
if (authors.length > 1 || item.count > this.maxItemCount)
|
if (authors.length > 1 || item.count > this.maxItemCount)
|
||||||
this.getAuthorBooks(item);//no await
|
this.getAuthorBooks(item);//no await
|
||||||
else
|
else
|
||||||
await this.getAuthorBooks(item);
|
if (await this.getAuthorBooks(item) === false) {
|
||||||
|
this.tableData = [];
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
result.push(item);
|
result.push(item);
|
||||||
|
|||||||
@@ -130,7 +130,7 @@ export default class BaseList {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
//подготовка
|
//подготовка
|
||||||
const response = await this.api.getBookLink(book.id);
|
const response = await this.api.getBookLink(book._uid);
|
||||||
|
|
||||||
const link = response.link;
|
const link = response.link;
|
||||||
const href = `${window.location.origin}${link}`;
|
const href = `${window.location.origin}${link}`;
|
||||||
@@ -164,7 +164,7 @@ export default class BaseList {
|
|||||||
}
|
}
|
||||||
} else if (action == 'bookInfo') {
|
} else if (action == 'bookInfo') {
|
||||||
//информация о книге
|
//информация о книге
|
||||||
const response = await this.api.getBookInfo(book.id);
|
const response = await this.api.getBookInfo(book._uid);
|
||||||
this.$emit('listEvent', {action: 'bookInfo', data: response.bookInfo});
|
this.$emit('listEvent', {action: 'bookInfo', data: response.bookInfo});
|
||||||
}
|
}
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
|
|||||||
@@ -185,7 +185,10 @@ class BookInfoDialog {
|
|||||||
return utils.sqlDateFormat(value);
|
return utils.sqlDateFormat(value);
|
||||||
|
|
||||||
if (nodePath == 'fileInfo/del')
|
if (nodePath == 'fileInfo/del')
|
||||||
return (value ? 'Да' : '');
|
return (value ? 'Да' : null);
|
||||||
|
|
||||||
|
if (nodePath == 'fileInfo/insno')
|
||||||
|
return (value ? value : null);
|
||||||
|
|
||||||
if (nodePath == 'titleInfo/author')
|
if (nodePath == 'titleInfo/author')
|
||||||
return value.split(',').join(', ');
|
return value.split(',').join(', ');
|
||||||
|
|||||||
4
package-lock.json
generated
4
package-lock.json
generated
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "inpx-web",
|
"name": "inpx-web",
|
||||||
"version": "1.2.2",
|
"version": "1.2.3",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 2,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "inpx-web",
|
"name": "inpx-web",
|
||||||
"version": "1.2.2",
|
"version": "1.2.3",
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"license": "CC0-1.0",
|
"license": "CC0-1.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "inpx-web",
|
"name": "inpx-web",
|
||||||
"version": "1.2.2",
|
"version": "1.2.3",
|
||||||
"author": "Book Pauk <bookpauk@gmail.com>",
|
"author": "Book Pauk <bookpauk@gmail.com>",
|
||||||
"license": "CC0-1.0",
|
"license": "CC0-1.0",
|
||||||
"repository": "bookpauk/inpx-web",
|
"repository": "bookpauk/inpx-web",
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ module.exports = {
|
|||||||
|
|
||||||
//поправить в случае, если были критические изменения в DbCreator или InpxParser
|
//поправить в случае, если были критические изменения в DbCreator или InpxParser
|
||||||
//иначе будет рассинхронизация между сервером и клиентом на уровне БД
|
//иначе будет рассинхронизация между сервером и клиентом на уровне БД
|
||||||
dbVersion: '6',
|
dbVersion: '7',
|
||||||
dbCacheSize: 5,
|
dbCacheSize: 5,
|
||||||
|
|
||||||
maxPayloadSize: 500,//in MB
|
maxPayloadSize: 500,//in MB
|
||||||
|
|||||||
@@ -165,19 +165,19 @@ class WebSocketController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async getBookLink(req, ws) {
|
async getBookLink(req, ws) {
|
||||||
if (!utils.hasProp(req, 'bookId'))
|
if (!utils.hasProp(req, 'bookUid'))
|
||||||
throw new Error(`bookId is empty`);
|
throw new Error(`bookUid is empty`);
|
||||||
|
|
||||||
const result = await this.webWorker.getBookLink(req.bookId);
|
const result = await this.webWorker.getBookLink(req.bookUid);
|
||||||
|
|
||||||
this.send(result, req, ws);
|
this.send(result, req, ws);
|
||||||
}
|
}
|
||||||
|
|
||||||
async getBookInfo(req, ws) {
|
async getBookInfo(req, ws) {
|
||||||
if (!utils.hasProp(req, 'bookId'))
|
if (!utils.hasProp(req, 'bookUid'))
|
||||||
throw new Error(`bookId is empty`);
|
throw new Error(`bookUid is empty`);
|
||||||
|
|
||||||
const result = await this.webWorker.getBookInfo(req.bookId);
|
const result = await this.webWorker.getBookInfo(req.bookUid);
|
||||||
|
|
||||||
this.send(result, req, ws);
|
this.send(result, req, ws);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -65,6 +65,8 @@ class DbCreator {
|
|||||||
let librateMap = new Map();//оценка
|
let librateMap = new Map();//оценка
|
||||||
let librateArr = [];
|
let librateArr = [];
|
||||||
|
|
||||||
|
let uidSet = new Set();//уникальные идентификаторы
|
||||||
|
|
||||||
//stats
|
//stats
|
||||||
let authorCount = 0;
|
let authorCount = 0;
|
||||||
let bookCount = 0;
|
let bookCount = 0;
|
||||||
@@ -221,13 +223,14 @@ class DbCreator {
|
|||||||
let filtered = false;
|
let filtered = false;
|
||||||
for (const rec of chunk) {
|
for (const rec of chunk) {
|
||||||
//сначала фильтр
|
//сначала фильтр
|
||||||
if (!filter(rec)) {
|
if (!filter(rec) || uidSet.has(rec._uid)) {
|
||||||
rec.id = 0;
|
rec.id = 0;
|
||||||
filtered = true;
|
filtered = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
rec.id = ++id;
|
rec.id = ++id;
|
||||||
|
uidSet.add(rec._uid);
|
||||||
|
|
||||||
if (!rec.del) {
|
if (!rec.del) {
|
||||||
bookCount++;
|
bookCount++;
|
||||||
@@ -269,6 +272,7 @@ class DbCreator {
|
|||||||
delMap = null;
|
delMap = null;
|
||||||
dateMap = null;
|
dateMap = null;
|
||||||
librateMap = null;
|
librateMap = null;
|
||||||
|
uidSet = null;
|
||||||
|
|
||||||
await db.close({table: 'book'});
|
await db.close({table: 'book'});
|
||||||
await db.freeMemory();
|
await db.freeMemory();
|
||||||
@@ -624,6 +628,12 @@ class DbCreator {
|
|||||||
stats.filesDelCount = res.filesDelCount;
|
stats.filesDelCount = res.filesDelCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//заодно добавим нужный индекс
|
||||||
|
await db.create({
|
||||||
|
in: 'book',
|
||||||
|
hash: {field: '_uid', type: 'string', depth: 100, unique: true},
|
||||||
|
});
|
||||||
|
|
||||||
countDone = true;
|
countDone = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
const path = require('path');
|
const path = require('path');
|
||||||
|
const crypto = require('crypto');
|
||||||
const ZipReader = require('./ZipReader');
|
const ZipReader = require('./ZipReader');
|
||||||
|
|
||||||
const collectionInfo = 'collection.info';
|
const collectionInfo = 'collection.info';
|
||||||
@@ -98,9 +99,13 @@ class InpxParser {
|
|||||||
if (line[line.length - 1] == '\x0D')
|
if (line[line.length - 1] == '\x0D')
|
||||||
line = line.substring(0, line.length - 1);
|
line = line.substring(0, line.length - 1);
|
||||||
|
|
||||||
|
const rec = {};
|
||||||
|
//уникальный идентификатор записи
|
||||||
|
const sha256 = crypto.createHash('sha256');
|
||||||
|
rec._uid = sha256.update(line).digest('base64');
|
||||||
|
|
||||||
//парсим запись
|
//парсим запись
|
||||||
const parts = line.split('\x04');
|
const parts = line.split('\x04');
|
||||||
const rec = {};
|
|
||||||
|
|
||||||
const len = (parts.length > structLen ? structLen : parts.length);
|
const len = (parts.length > structLen ? structLen : parts.length);
|
||||||
for (let i = 0; i < len; i++) {
|
for (let i = 0; i < len; i++) {
|
||||||
|
|||||||
@@ -58,9 +58,9 @@ class RemoteLib {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async downloadBook(bookId) {
|
async downloadBook(bookUid) {
|
||||||
try {
|
try {
|
||||||
const response = await await this.wsRequest({action: 'get-book-link', bookId});
|
const response = await await this.wsRequest({action: 'get-book-link', bookUid});
|
||||||
const link = response.link;
|
const link = response.link;
|
||||||
|
|
||||||
const buf = await this.down.load(`${this.remoteHost}${link}`, {decompress: false});
|
const buf = await this.down.load(`${this.remoteHost}${link}`, {decompress: false});
|
||||||
|
|||||||
@@ -354,7 +354,7 @@ class WebWorker {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async restoreBook(bookId, bookPath, downFileName) {
|
async restoreBook(bookUid, bookPath, downFileName) {
|
||||||
const db = this.db;
|
const db = this.db;
|
||||||
|
|
||||||
let extractedFile = '';
|
let extractedFile = '';
|
||||||
@@ -364,7 +364,7 @@ class WebWorker {
|
|||||||
extractedFile = await this.extractBook(bookPath);
|
extractedFile = await this.extractBook(bookPath);
|
||||||
hash = await utils.getFileHash(extractedFile, 'sha256', 'hex');
|
hash = await utils.getFileHash(extractedFile, 'sha256', 'hex');
|
||||||
} else {
|
} else {
|
||||||
hash = await this.remoteLib.downloadBook(bookId);
|
hash = await this.remoteLib.downloadBook(bookUid);
|
||||||
}
|
}
|
||||||
|
|
||||||
const link = `${this.config.filesPathStatic}/${hash}`;
|
const link = `${this.config.filesPathStatic}/${hash}`;
|
||||||
@@ -402,7 +402,7 @@ class WebWorker {
|
|||||||
return link;
|
return link;
|
||||||
}
|
}
|
||||||
|
|
||||||
async getBookLink(bookId) {
|
async getBookLink(bookUid) {
|
||||||
this.checkMyState();
|
this.checkMyState();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -410,11 +410,11 @@ class WebWorker {
|
|||||||
let link = '';
|
let link = '';
|
||||||
|
|
||||||
//найдем bookPath и downFileName
|
//найдем bookPath и downFileName
|
||||||
let rows = await db.select({table: 'book', where: `@@id(${db.esc(bookId)})`});
|
let rows = await db.select({table: 'book', where: `@@hash('_uid', ${db.esc(bookUid)})`});
|
||||||
if (!rows.length)
|
if (!rows.length)
|
||||||
throw new Error('404 Файл не найден');
|
throw new Error('404 Файл не найден');
|
||||||
|
|
||||||
const book = rows[0];
|
const book = rows[0];
|
||||||
let downFileName = book.file;
|
let downFileName = book.file;
|
||||||
const author = book.author.split(',');
|
const author = book.author.split(',');
|
||||||
const at = [author[0], book.title];
|
const at = [author[0], book.title];
|
||||||
@@ -443,7 +443,7 @@ class WebWorker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!link) {
|
if (!link) {
|
||||||
link = await this.restoreBook(bookId, bookPath, downFileName)
|
link = await this.restoreBook(bookUid, bookPath, downFileName)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!link)
|
if (!link)
|
||||||
@@ -458,13 +458,13 @@ class WebWorker {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async getBookInfo(bookId) {
|
async getBookInfo(bookUid) {
|
||||||
this.checkMyState();
|
this.checkMyState();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const db = this.db;
|
const db = this.db;
|
||||||
|
|
||||||
let bookInfo = await this.getBookLink(bookId);
|
let bookInfo = await this.getBookLink(bookUid);
|
||||||
const hash = path.basename(bookInfo.link);
|
const hash = path.basename(bookInfo.link);
|
||||||
const bookFile = `${this.config.filesDir}/${hash}`;
|
const bookFile = `${this.config.filesDir}/${hash}`;
|
||||||
const bookFileInfo = `${bookFile}.i.json`;
|
const bookFileInfo = `${bookFile}.i.json`;
|
||||||
@@ -472,7 +472,9 @@ class WebWorker {
|
|||||||
const restoreBookInfo = async(info) => {
|
const restoreBookInfo = async(info) => {
|
||||||
const result = {};
|
const result = {};
|
||||||
|
|
||||||
const rows = await db.select({table: 'book', where: `@@id(${db.esc(bookId)})`});
|
let rows = await db.select({table: 'book', where: `@@hash('_uid', ${db.esc(bookUid)})`});
|
||||||
|
if (!rows.length)
|
||||||
|
throw new Error('404 Файл не найден');
|
||||||
const book = rows[0];
|
const book = rows[0];
|
||||||
|
|
||||||
result.book = book;
|
result.book = book;
|
||||||
|
|||||||
Reference in New Issue
Block a user