瀏覽代碼

Добавлена возможность фильтрации по авторам при формировании поисковой БД.
Критерии фильтрации должны находиться в файле inpx-web-filter.json

Book Pauk 2 年之前
父節點
當前提交
904e3e6c2f
共有 4 個文件被更改,包括 107 次插入8 次删除
  1. 74 6
      server/core/DbCreator.js
  2. 28 0
      server/core/InpxHashCreator.js
  3. 4 2
      server/core/WebWorker.js
  4. 1 0
      server/index.js

+ 74 - 6
server/core/DbCreator.js

@@ -1,4 +1,7 @@
+const fs = require('fs-extra');
+
 const InpxParser = require('./InpxParser');
+const InpxHashCreator = require('./InpxHashCreator');
 const utils = require('./utils');
 
 const emptyFieldValue = '?';
@@ -8,6 +11,29 @@ class DbCreator {
         this.config = config;
     }
 
+    async loadInpxFilter() {
+        const inpxFilterFile = this.config.inpxFilterFile;
+
+        if (await fs.pathExists(inpxFilterFile)) {
+            let filter = await fs.readFile(inpxFilterFile, 'utf8');
+            filter = JSON.parse(filter);
+
+            if (filter.includeAuthors) {
+                filter.includeAuthors = filter.includeAuthors.map(a => a.toLowerCase());
+                filter.includeSet = new Set(filter.includeAuthors);
+            }
+
+            if (filter.excludeAuthors) {
+                filter.excludeAuthors = filter.excludeAuthors.map(a => a.toLowerCase());
+                filter.excludeSet = new Set(filter.excludeAuthors);
+            }
+
+            return filter;
+        } else {
+            return false;
+        }
+    }
+
     //процедура формировани БД несколько усложнена, в целях экономии памяти
     async run(db, callback) {
         const config = this.config;
@@ -44,10 +70,37 @@ class DbCreator {
         callback({recsLoaded});
         let chunkNum = 0;
 
+        //фильтр по авторам
+        const inpxFilter = await this.loadInpxFilter();
+        let filterAuthor = () => true;
+        if (inpxFilter) {
+            filterAuthor = (author) => {
+                if (!author)
+                    author = emptyFieldValue;
+
+                author = author.toLowerCase();
+
+                let excluded = false;
+                if (inpxFilter.excludeSet) {
+                    const authors = author.split(',');
+
+                    for (const a of authors) {
+                        if (inpxFilter.excludeSet.has(a)) {
+                            excluded = true;
+                            break;
+                        }
+                    }
+                }
+
+                return (!inpxFilter.includeSet || inpxFilter.includeSet.has(author)) && !excluded
+                ;
+            };
+        }
+
+        //вспомогательные функции
         const splitAuthor = (author) => {
-            if (!author) {
+            if (!author)
                 author = emptyFieldValue;
-            }
 
             const result = author.split(',');
             if (result.length > 1)
@@ -69,7 +122,15 @@ class DbCreator {
 
         let id = 0;
         const parsedCallback = async(chunk) => {
+            let filtered = false;
             for (const rec of chunk) {
+                //сначала фильтр по авторам
+                if (!filterAuthor(rec.author)) {
+                    rec.id = 0;
+                    filtered = true;
+                    continue;
+                }
+
                 rec.id = ++id;
 
                 if (!rec.del) {
@@ -116,7 +177,14 @@ class DbCreator {
                 }
             }
 
-            await db.insert({table: 'book', rows: chunk});
+            let saveChunk = [];
+            if (filtered) {
+                saveChunk = chunk.filter(r => r.id);
+            } else {
+                saveChunk = chunk;
+            }
+
+            await db.insert({table: 'book', rows: saveChunk});
 
             recsLoaded += chunk.length;
             callback({recsLoaded});
@@ -373,12 +441,12 @@ class DbCreator {
         };
         //console.log(stats);
 
-        const inpxHash = await utils.getFileHash(config.inpxFile, 'sha256', 'hex');
+        const inpxHashCreator = new InpxHashCreator(config);
 
         await db.insert({table: 'config', rows: [
-            {id: 'inpxInfo', value: parser.info},
+            {id: 'inpxInfo', value: (inpxFilter && inpxFilter.info ? inpxFilter.info : parser.info)},
             {id: 'stats', value: stats},
-            {id: 'inpxHash', value: inpxHash},
+            {id: 'inpxHash', value: await inpxHashCreator.getHash()},
         ]});
 
         //сохраним поисковые таблицы

+ 28 - 0
server/core/InpxHashCreator.js

@@ -0,0 +1,28 @@
+const fs = require('fs-extra');
+
+const utils = require('./utils');
+
+//поправить в случае, если изменился порядок формирования id для авторов в DbCreator
+//иначе будет неправильно работать кеширование на клиенте
+const dbCreatorVersion = '1';
+
+class InpxHashCreator {
+    constructor(config) {
+        this.config = config;
+    }
+
+    async getHash() {
+        const config = this.config;
+
+        let inpxFilterHash = '';
+        if (await fs.pathExists(config.inpxFilterFile))
+            inpxFilterHash = await utils.getFileHash(config.inpxFilterFile, 'sha256', 'hex');
+
+        const joinedHash = dbCreatorVersion + inpxFilterHash +
+            await utils.getFileHash(config.inpxFile, 'sha256', 'hex');
+
+        return utils.getBufHash(joinedHash, 'sha256', 'hex');
+    }
+}
+
+module.exports = InpxHashCreator;

+ 4 - 2
server/core/WebWorker.js

@@ -9,6 +9,7 @@ const WorkerState = require('./WorkerState');
 const { JembaDbThread } = require('jembadb');
 const DbCreator = require('./DbCreator');
 const DbSearcher = require('./DbSearcher');
+const InpxHashCreator = require('./InpxHashCreator');
 
 const ayncExit = new (require('./AsyncExit'))();
 const log = new (require('./AppLogger'))().log;//singleton
@@ -497,13 +498,14 @@ class WebWorker {
         if (!inpxCheckInterval)
             return;
 
+        const inpxHashCreator = new InpxHashCreator(this.config);
+
         while (1) {// eslint-disable-line no-constant-condition
             try {
                 while (this.myState != ssNormal)
                     await utils.sleep(1000);
 
-                log('check inpx file for changes');
-                const newInpxHash = await utils.getFileHash(this.config.inpxFile, 'sha256', 'hex');
+                const newInpxHash = await inpxHashCreator.getHash();
 
                 const dbConfig = await this.dbConfig();
                 const currentInpxHash = (dbConfig.inpxHash ? dbConfig.inpxHash : '');

+ 1 - 0
server/index.js

@@ -103,6 +103,7 @@ async function init() {
     }
 
     config.recreateDb = argv.recreate || false;
+    config.inpxFilterFile = `${config.execDir}/inpx-web-filter.json`;
 
     //app
     const appDir = `${config.publicDir}/app`;