Merge branch 'SEARCH-182' into SEARCH-154

# Conflicts:
#	package.json
This commit is contained in:
Keerthi Niranjan 2017-08-07 12:20:00 +05:30
commit 6634e41953
12 changed files with 520 additions and 4 deletions

177
demo/search.html Normal file
View File

@ -0,0 +1,177 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Search</title>
<style>
table, th, td {
border: 1px solid black;
border-collapse: collapse;
padding: 5px;
text-align: center;
}
.hidden {
display: none;
}
input {
padding: 5px;
margin: 2px 0;
border: 1px solid #ccc;
}
label {
padding-right: 10px;
}
button {
padding: 10px;
background-color: rgba(0, 64, 98, 0.7);
color: white;
}
</style>
</head>
<body>
<div style="padding: 20px;">
<h1>Symphony Electron Search API Demo</h1>
<div>
<p>Search</p>
</div>
<div>
<label for="query">Query:</label><input id="query" size=60>
</div>
<br>
<div>
<label for="offset">Offset:</label><input id="offset" type="number" value="0" size=5>
<label for="limit">Limit:</label><input id="limit" type="number" value="25" size=5>
</div>
<br>
<div>
<label for="start">Start:</label><input id="start" type="date">
<label for="end">End:</label><input id="end" type="date">
</div>
<br>
<div>
<label for="senderId">SenderId:</label><input id="senderId" size=20>
</div>
<br>
<div>
<label for="threadId">ThreadId:</label><input id="threadId" size=20>
</div>
<br>
<div>
<button id='search'>Search</button>
</div>
<br>
<div>
<label for="var1">var1:</label><input id="var1" type="number" value="0" size=5>
</div>
<div>
<label for="realTimeIndexing">Real Time Indexing:</label><input placeholder="Pass array of messages:"
id="realTimeIndexing">
<button id='sendMessage'>Send</button>
</div>
<br>
<div>
<label for="batchNumber">Batch Number: </label><input placeholder="Ex: batch1, batch2" id="batchNumber">
<button id='index'>Index Messages</button>
<button id='merge'>Merge</button>
</div>
<br>
<div>
<p>Results:</p>
<p id="results"></p>
<table id="table" class="hidden" style="width:100%">
<tr>
<th>ThreadId</th>
<th>SenderId</th>
<th>Text</th>
</tr>
</table>
<br>
</div>
</div>
</body>
<script>
var search = new ssf.Search("testUser1");
var buttonEl = document.getElementById('search');
var merge = document.getElementById('merge');
var buttonIndex = document.getElementById('index');
var queryEl = document.getElementById('query');
var offsetEl = document.getElementById('offset');
var limitEl = document.getElementById('limit');
var startEl = document.getElementById('start');
var endEl = document.getElementById('end');
var resultsEl = document.getElementById('results');
var senderIdEl = document.getElementById('senderId');
var threadIdEl = document.getElementById('threadId');
var var1El = document.getElementById('var1');
var table = document.getElementById('table');
var sendMessage = document.getElementById('sendMessage');
var realTimeIndexing = document.getElementById('realTimeIndexing');
var batchNumber = document.getElementById('batchNumber');
buttonIndex.addEventListener('click', function () {
let batchIndex = batchNumber.value;
search.readJson(batchIndex).then(function (res) {
search.indexBatch(res).then(function () {
resultsEl.innerHTML = "Index created";
});
}).catch(function (err) {
console.log(err);
});
});
buttonEl.addEventListener('click', function () {
if (!search.isLibInit()) {
alert('Library is not initiated. Init first...');
return;
}
let out;
table.innerHTML = '';
table.classList.remove('hidden');
let startDate = new Date(startEl.value);
let endDate = new Date(endEl.value);
search.query(queryEl.value, senderIdEl.value, threadIdEl.value, null, startDate, endDate, limitEl.value, offsetEl.value, 0).then(function (result) {
out = result;
var th = document.createElement('tr');
var th1 = document.createElement('td');
th1.innerText = "ThreadId";
var th2 = document.createElement('td');
th2.innerText = 'SenderId';
var th3 = document.createElement('td');
th3.innerText = 'Text';
th.appendChild(th1);
th.appendChild(th2);
th.appendChild(th3);
table.appendChild(th);
out.messages.forEach(function (msg) {
var tr = document.createElement('tr');
var t1 = document.createElement('td');
t1.innerText = msg.threadId;
var t2 = document.createElement('td');
t2.innerText = msg.senderId;
var t3 = document.createElement('td');
t3.innerText = msg.text;
tr.appendChild(t1);
tr.appendChild(t2);
tr.appendChild(t3);
table.appendChild(tr);
});
}).catch(function (err) {
resultsEl.innerHTML = err;
});
});
sendMessage.addEventListener('click', function () {
let message = JSON.parse(realTimeIndexing.value);
search.realTimeIndexing(message);
});
merge.addEventListener('click', function () {
search.mergeIndexBatches();
})
</script>
</html>

View File

@ -46,6 +46,7 @@
<ROW Directory="Symphony_Dir" Directory_Parent="ProgramMenuFolder" DefaultDir="Symphony"/>
<ROW Directory="TARGETDIR" DefaultDir="SourceDir"/>
<ROW Directory="config_Dir" Directory_Parent="APPDIR" DefaultDir="config"/>
<ROW Directory="library_Dir" Directory_Parent="APPDIR" DefaultDir="library"/>
<ROW Directory="locales_Dir" Directory_Parent="APPDIR" DefaultDir="locales"/>
<ROW Directory="resources_Dir" Directory_Parent="APPDIR" DefaultDir="RESOUR~1|resources"/>
</COMPONENT>
@ -102,8 +103,14 @@
<ROW Component="blink_image_resources_200_percent.pak" ComponentId="{56AB17A5-B690-4CBE-A39D-512381AAAFE1}" Directory_="APPDIR" Attributes="0" KeyPath="blink_image_resources_200_percent.pak" Type="0"/>
<ROW Component="d3dcompiler_47.dll" ComponentId="{C7B87C02-3116-43A8-A70B-3592B70E6AC8}" Directory_="APPDIR" Attributes="256" KeyPath="d3dcompiler_47.dll"/>
<ROW Component="ffmpeg.dll" ComponentId="{A1C4A332-3490-44D8-A5C9-9523889B488B}" Directory_="APPDIR" Attributes="256" KeyPath="ffmpeg.dll"/>
<ROW Component="indexvalidator.exe" ComponentId="{DF058776-545D-4E62-9F4A-758FFDE21FCD}" Directory_="APPDIR" Attributes="256" KeyPath="indexvalidator.exe"/>
<ROW Component="indexvalidatorx64.exe" ComponentId="{C542F166-F7BD-4807-861C-E60DC54DDC22}" Directory_="library_Dir" Attributes="256" KeyPath="indexvalidatorx64.exe"/>
<ROW Component="indexvalidatorx86.exe" ComponentId="{48CD723D-0520-48F0-A3E8-DCFA0545A964}" Directory_="library_Dir" Attributes="0" KeyPath="indexvalidatorx86.exe"/>
<ROW Component="libEGL.dll" ComponentId="{8EEC76AB-3601-4D11-B13E-32EC2A38C539}" Directory_="APPDIR" Attributes="256" KeyPath="libEGL.dll"/>
<ROW Component="libGLESv2.dll" ComponentId="{0E8B8B21-B4C0-45C9-95D3-637FD93A4EC0}" Directory_="APPDIR" Attributes="256" KeyPath="libGLESv2.dll"/>
<ROW Component="libsymphonysearch.dll" ComponentId="{E97AC27E-7052-43F5-A012-4570714A5195}" Directory_="APPDIR" Attributes="256" KeyPath="libsymphonysearch.dll"/>
<ROW Component="libsymphonysearchx64.dll" ComponentId="{9929A8AB-80F5-4A43-8EA2-F4D46319CAB4}" Directory_="library_Dir" Attributes="256" KeyPath="libsymphonysearchx64.dll"/>
<ROW Component="libsymphonysearchx86.dll" ComponentId="{AFE15B0C-1615-4FD4-8E35-E867FBE31F5D}" Directory_="library_Dir" Attributes="0" KeyPath="libsymphonysearchx86.dll"/>
<ROW Component="msvcp140.dll" ComponentId="{93A6289C-CF23-4BB8-A579-7FDDD1D15591}" Directory_="APPDIR" Attributes="256" KeyPath="msvcp140.dll"/>
<ROW Component="node.dll" ComponentId="{C0972355-339E-438C-94A3-74174DE4C6B6}" Directory_="APPDIR" Attributes="256" KeyPath="node.dll"/>
<ROW Component="ucrtbase.dll" ComponentId="{16D802A3-DAD4-4BF4-AD64-88D6F63F5D1E}" Directory_="APPDIR" Attributes="256" KeyPath="ucrtbase.dll"/>
@ -111,7 +118,7 @@
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiFeatsComponent">
<ROW Feature="D564007E3BBE4F85950A09B470A7CA65" Title="Visual C++ Redistributable for Visual Studio 2013 x86" Description="Visual C++ Redistributable for Visual Studio 2013 x86" Display="3" Level="1" Attributes="0" Components="AI_CustomARPName"/>
<ROW Feature="MainFeature" Title="MainFeature" Description="Description" Display="1" Level="1" Directory_="APPDIR" Attributes="0" Components="AI_CustomARPName PodUrl ProductInformation ScreenSnippet.exe Symphony Symphony.config Symphony.exe am.pak apimswincoreconsolel110.dll apimswincoredatetimel110.dll apimswincoredebugl110.dll apimswincoreerrorhandlingl110.dll apimswincorefilel110.dll apimswincorefilel120.dll apimswincorefilel210.dll apimswincorehandlel110.dll apimswincoreheapl110.dll apimswincoreinterlockedl110.dll apimswincorelibraryloaderl110.dll apimswincorelocalizationl120.dll apimswincorememoryl110.dll apimswincorenamedpipel110.dll apimswincoreprocessenvironmentl110.dll apimswincoreprocessthreadsl110.dll apimswincoreprocessthreadsl111.dll apimswincoreprofilel110.dll apimswincorertlsupportl110.dll apimswincorestringl110.dll apimswincoresynchl110.dll apimswincoresynchl120.dll apimswincoresysinfol110.dll apimswincoretimezonel110.dll apimswincoreutill110.dll apimswincrtconiol110.dll apimswincrtconvertl110.dll apimswincrtenvironmentl110.dll apimswincrtfilesysteml110.dll apimswincrtheapl110.dll apimswincrtlocalel110.dll apimswincrtmathl110.dll apimswincrtmultibytel110.dll apimswincrtprivatel110.dll apimswincrtprocessl110.dll apimswincrtruntimel110.dll apimswincrtstdiol110.dll apimswincrtstringl110.dll apimswincrttimel110.dll apimswincrtutilityl110.dll appupdate.yml blink_image_resources_200_percent.pak d3dcompiler_47.dll ffmpeg.dll libEGL.dll libGLESv2.dll msvcp140.dll node.dll ucrtbase.dll vcruntime140.dll"/>
<ROW Feature="MainFeature" Title="MainFeature" Description="Description" Display="1" Level="1" Directory_="APPDIR" Attributes="0" Components="AI_CustomARPName PodUrl ProductInformation ScreenSnippet.exe Symphony Symphony.config Symphony.exe am.pak apimswincoreconsolel110.dll apimswincoredatetimel110.dll apimswincoredebugl110.dll apimswincoreerrorhandlingl110.dll apimswincorefilel110.dll apimswincorefilel120.dll apimswincorefilel210.dll apimswincorehandlel110.dll apimswincoreheapl110.dll apimswincoreinterlockedl110.dll apimswincorelibraryloaderl110.dll apimswincorelocalizationl120.dll apimswincorememoryl110.dll apimswincorenamedpipel110.dll apimswincoreprocessenvironmentl110.dll apimswincoreprocessthreadsl110.dll apimswincoreprocessthreadsl111.dll apimswincoreprofilel110.dll apimswincorertlsupportl110.dll apimswincorestringl110.dll apimswincoresynchl110.dll apimswincoresynchl120.dll apimswincoresysinfol110.dll apimswincoretimezonel110.dll apimswincoreutill110.dll apimswincrtconiol110.dll apimswincrtconvertl110.dll apimswincrtenvironmentl110.dll apimswincrtfilesysteml110.dll apimswincrtheapl110.dll apimswincrtlocalel110.dll apimswincrtmathl110.dll apimswincrtmultibytel110.dll apimswincrtprivatel110.dll apimswincrtprocessl110.dll apimswincrtruntimel110.dll apimswincrtstdiol110.dll apimswincrtstringl110.dll apimswincrttimel110.dll apimswincrtutilityl110.dll appupdate.yml blink_image_resources_200_percent.pak d3dcompiler_47.dll ffmpeg.dll indexvalidator.exe indexvalidatorx64.exe indexvalidatorx86.exe libEGL.dll libGLESv2.dll libsymphonysearch.dll libsymphonysearchx64.dll libsymphonysearchx86.dll msvcp140.dll node.dll ucrtbase.dll vcruntime140.dll"/>
<ATTRIBUTE name="CurrentFeature" value="MainFeature"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiFilesComponent">
@ -194,12 +201,18 @@
<ROW File="hu.pak" Component_="am.pak" FileName="hu.pak" Attributes="0" SourcePath="..\..\dist\win-unpacked\locales\hu.pak" SelfReg="false" NextFile="id.pak"/>
<ROW File="icudtl.dat" Component_="blink_image_resources_200_percent.pak" FileName="icudtl.dat" Attributes="0" SourcePath="..\..\dist\win-unpacked\icudtl.dat" SelfReg="false" NextFile="libEGL.dll"/>
<ROW File="id.pak" Component_="am.pak" FileName="id.pak" Attributes="0" SourcePath="..\..\dist\win-unpacked\locales\id.pak" SelfReg="false" NextFile="it.pak"/>
<ROW File="indexvalidator.exe" Component_="indexvalidator.exe" FileName="INDEXV~1.EXE|indexvalidator.exe" Attributes="0" SourcePath="..\..\indexvalidator.exe" SelfReg="false" NextFile="libsymphonysearch.dll" DigSign="true"/>
<ROW File="indexvalidatorx64.exe" Component_="indexvalidatorx64.exe" FileName="INDEXV~1.EXE|indexvalidator-x64.exe" Attributes="0" SourcePath="..\..\library\indexvalidator-x64.exe" SelfReg="false" NextFile="indexvalidatorx86.exe" DigSign="true"/>
<ROW File="indexvalidatorx86.exe" Component_="indexvalidatorx86.exe" FileName="INDEXV~2.EXE|indexvalidator-x86.exe" Attributes="0" SourcePath="..\..\library\indexvalidator-x86.exe" SelfReg="false" NextFile="libsymphonysearchx64.dll" DigSign="true"/>
<ROW File="it.pak" Component_="am.pak" FileName="it.pak" Attributes="0" SourcePath="..\..\dist\win-unpacked\locales\it.pak" SelfReg="false" NextFile="ja.pak"/>
<ROW File="ja.pak" Component_="am.pak" FileName="ja.pak" Attributes="0" SourcePath="..\..\dist\win-unpacked\locales\ja.pak" SelfReg="false" NextFile="kn.pak"/>
<ROW File="kn.pak" Component_="am.pak" FileName="kn.pak" Attributes="0" SourcePath="..\..\dist\win-unpacked\locales\kn.pak" SelfReg="false" NextFile="ko.pak"/>
<ROW File="ko.pak" Component_="am.pak" FileName="ko.pak" Attributes="0" SourcePath="..\..\dist\win-unpacked\locales\ko.pak" SelfReg="false" NextFile="lt.pak"/>
<ROW File="libEGL.dll" Component_="libEGL.dll" FileName="libEGL.dll" Attributes="0" SourcePath="..\..\dist\win-unpacked\libEGL.dll" SelfReg="false" NextFile="libGLESv2.dll"/>
<ROW File="libGLESv2.dll" Component_="libGLESv2.dll" FileName="LIBGLE~1.DLL|libGLESv2.dll" Attributes="0" SourcePath="..\..\dist\win-unpacked\libGLESv2.dll" SelfReg="false" NextFile="LICENSE.electron.txt"/>
<ROW File="libsymphonysearch.dll" Component_="libsymphonysearch.dll" FileName="LIBSYM~1.DLL|libsymphonysearch.dll" Attributes="0" SourcePath="..\..\libsymphonysearch.dll" SelfReg="false" NextFile="indexvalidatorx64.exe"/>
<ROW File="libsymphonysearchx64.dll" Component_="libsymphonysearchx64.dll" FileName="LIBSYM~1.DLL|libsymphonysearch-x64.dll" Attributes="0" SourcePath="..\..\library\libsymphonysearch-x64.dll" SelfReg="false" NextFile="libsymphonysearchx86.dll"/>
<ROW File="libsymphonysearchx86.dll" Component_="libsymphonysearchx86.dll" FileName="LIBSYM~2.DLL|libsymphonysearch-x86.dll" Attributes="0" SourcePath="..\..\library\libsymphonysearch-x86.dll" SelfReg="false"/>
<ROW File="lt.pak" Component_="am.pak" FileName="lt.pak" Attributes="0" SourcePath="..\..\dist\win-unpacked\locales\lt.pak" SelfReg="false" NextFile="lv.pak"/>
<ROW File="lv.pak" Component_="am.pak" FileName="lv.pak" Attributes="0" SourcePath="..\..\dist\win-unpacked\locales\lv.pak" SelfReg="false" NextFile="ml.pak"/>
<ROW File="ml.pak" Component_="am.pak" FileName="ml.pak" Attributes="0" SourcePath="..\..\dist\win-unpacked\locales\ml.pak" SelfReg="false" NextFile="mr.pak"/>
@ -228,7 +241,7 @@
<ROW File="ucrtbase.dll" Component_="ucrtbase.dll" FileName="ucrtbase.dll" Attributes="0" SourcePath="..\..\dist\win-unpacked\ucrtbase.dll" SelfReg="false" NextFile="vcruntime140.dll"/>
<ROW File="ui_resources_200_percent.pak" Component_="blink_image_resources_200_percent.pak" FileName="UI_RES~1.PAK|ui_resources_200_percent.pak" Attributes="0" SourcePath="..\..\dist\win-unpacked\ui_resources_200_percent.pak" SelfReg="false" NextFile="views_resources_200_percent.pak"/>
<ROW File="uk.pak" Component_="am.pak" FileName="uk.pak" Attributes="0" SourcePath="..\..\dist\win-unpacked\locales\uk.pak" SelfReg="false" NextFile="vi.pak"/>
<ROW File="vcruntime140.dll" Component_="vcruntime140.dll" FileName="VCRUNT~1.DLL|vcruntime140.dll" Attributes="0" SourcePath="..\..\dist\win-unpacked\vcruntime140.dll" SelfReg="false"/>
<ROW File="vcruntime140.dll" Component_="vcruntime140.dll" FileName="VCRUNT~1.DLL|vcruntime140.dll" Attributes="0" SourcePath="..\..\dist\win-unpacked\vcruntime140.dll" SelfReg="false" NextFile="indexvalidator.exe"/>
<ROW File="vi.pak" Component_="am.pak" FileName="vi.pak" Attributes="0" SourcePath="..\..\dist\win-unpacked\locales\vi.pak" SelfReg="false" NextFile="zhCN.pak"/>
<ROW File="views_resources_200_percent.pak" Component_="blink_image_resources_200_percent.pak" FileName="VIEWS_~1.PAK|views_resources_200_percent.pak" Attributes="0" SourcePath="..\..\dist\win-unpacked\views_resources_200_percent.pak" SelfReg="false" NextFile="am.pak"/>
<ROW File="zhCN.pak" Component_="am.pak" FileName="zh-CN.pak" Attributes="0" SourcePath="..\..\dist\win-unpacked\locales\zh-CN.pak" SelfReg="false" NextFile="zhTW.pak"/>

View File

@ -111,6 +111,8 @@ function createAPI() {
*/
ScreenSnippet: remote.require('./screenSnippet/ScreenSnippet.js').ScreenSnippet,
Search: remote.require('./search/search.js').Search,
/**
* Brings window forward and gives focus.
* @param {String} windowName Name of window. Note: main window name is 'main'

239
js/search/search.js Normal file
View File

@ -0,0 +1,239 @@
'use strict';
const fs = require('fs');
const randomString = require('randomstring');
const electron = require('electron');
const childProcess = require('child_process');
const app = electron.app;
const path = require('path');
const isDevEnv = require('../utils/misc.js').isDevEnv;
const isMac = require('../utils/misc.js').isMac;
// Search library
const libSymphonySearch = require('./searchLibrary');
// Path for the exec file and the user data folder
const userData = path.join(app.getPath('userData'));
const execPath = path.dirname(app.getPath('exe'));
// Constants paths for temp indexing folders
const TEMP_BATCH_INDEX_FOLDER = isDevEnv ? './data/temp_batch_indexes' : path.join(userData, 'data/temp_batch_indexes');
const TEMP_REALTIME_INDEX = isDevEnv ? './data/temp_realtime_index' : path.join(userData, 'data/temp_realtime_index');
const INDEX_PREFIX = isDevEnv ? './data/search_index' : path.join(userData, 'data/search_index');
const INDEX_DATA_FOLDER = isDevEnv ? './data' : path.join(userData, 'data');
const SEARCH_PERIOD_SUBTRACTOR = 3 * 31 * 24 * 60 * 60 * 1000;//3 months
const MINIMUM_DATE = '0000000000000';
const MAXIMUM_DATE = '9999999999999';
const INDEX_VERSION = 'v1';
const INTERNATIONAL_CHARACTER_CODES = '\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u08A0-\u08B2\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58\u0C59\u0C60\u0C61\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D60\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F4\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16F1-\u16F8\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1877\u1880-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19C1-\u19C7\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1CE9-\u1CEC\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2183\u2184\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005\u3006\u3031-\u3035\u303B\u303C\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FCC\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6E5\uA717-\uA71F\uA722-\uA788\uA78B-\uA78E\uA790-\uA7AD\uA7B0\uA7B1\uA7F7-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uA9E0-\uA9E4\uA9E6-\uA9EF\uA9FA-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB5F\uAB64\uAB65\uABC0-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC';
const INVALID_CHARACTERS_REGEX = new RegExp('[^#$_a-z0-9' + INTERNATIONAL_CHARACTER_CODES + ']+', 'gmi');
const winArchPath = process.arch === 'ia32' ? 'library/indexvalidator-x86.exe' : 'library/indexvalidator-x64.exe';
const rootPath = isMac ? 'library/indexvalidator.exec' : winArchPath;
const productionPath = path.join(execPath, isMac ? '..' : '', rootPath);
const devPath = path.join(__dirname, '..', '..', rootPath);
const libraryPath = isDevEnv ? devPath : productionPath;
let INDEX_VALIDATOR = libraryPath;
const SORT_BY_SCORE = 0;
const BATCH_RANDOM_INDEX_PATH_LENGTH = 20;
class Search {
constructor(userId) {
this.isInitialized = false;
this.userId = userId;
this.startIndexingFromDate = (new Date().getTime() - SEARCH_PERIOD_SUBTRACTOR).toString();
this.indexFolderName = INDEX_PREFIX + '_' + userId + '_' + INDEX_VERSION;
this.dataFolder = INDEX_DATA_FOLDER;
this.realTimeIndex = TEMP_REALTIME_INDEX;
this.batchIndex = TEMP_BATCH_INDEX_FOLDER;
this.messageData = [];
this.init();
}
initLib() {
return new Promise((resolve) => {
if (!this.isInitialized) {
this.isInitialized = true;
}
resolve(libSymphonySearch.symSEInit());
});
}
isLibInit() {
return this.initLib();
}
init() {
libSymphonySearch.symSEInit();
libSymphonySearch.symSEEnsureFolderExists(this.dataFolder);
libSymphonySearch.symSERemoveFolder(this.realTimeIndex);
libSymphonySearch.symSERemoveFolder(this.batchIndex);
Search.indexValidator(this.indexFolderName);
Search.indexValidator(this.realTimeIndex);
let indexDateStartFrom = new Date().getTime() - SEARCH_PERIOD_SUBTRACTOR;
libSymphonySearch.symSEDeleteMessages(this.indexFolderName, null,
MINIMUM_DATE, indexDateStartFrom.toString());
this.isInitialized = true;
}
indexBatch(messages) {
return new Promise((resolve, reject) => {
if (!this.isInitialized) {
reject()
}
let indexId = randomString.generate(BATCH_RANDOM_INDEX_PATH_LENGTH);
libSymphonySearch.symSECreatePartialIndexAsync(this.batchIndex, indexId, JSON.stringify(messages), function (err, res) {
if (err) reject(err);
resolve(res);
});
});
}
mergeIndexBatches() {
let self = this;
libSymphonySearch.symSEMergePartialIndexAsync(this.indexFolderName, this.batchIndex, function (err) {
if (err) throw err;
libSymphonySearch.symSERemoveFolder(self.batchIndex)
});
}
realTimeIndexing(message) {
libSymphonySearch.symSEIndexRealTime(this.realTimeIndex, JSON.stringify(message));
}
readJson(batch) {
let self = this;
return new Promise((resolve, reject) => {
let dirPath = path.join(execPath, isMac ? '..' : '', 'msgsjson', batch);
let messageFolderPath = isDevEnv ? path.join('./msgsjson', batch) : dirPath;
let files = fs.readdirSync(messageFolderPath);
self.messageData = [];
files.forEach(function (file) {
let tempPath = path.join(messageFolderPath, file);
let data = fs.readFileSync(tempPath, "utf8");
if (data) {
self.messageData.push(JSON.parse(data));
resolve(self.messageData);
} else {
reject("err on reading files")
}
});
});
}
query(query, senderIds, threadIds, attachments, startDate,
endDate, limit, offset, sortOrder) {
let _limit = limit;
let _offset = offset;
let _sortOrder = sortOrder;
return new Promise((resolve, reject) => {
if (!this.isInitialized) {
reject(-1);
}
let q = Search.constructQuery(query, senderIds, threadIds, attachments);
if (q === undefined) {
reject(-2);
}
let sd = new Date().getTime() - SEARCH_PERIOD_SUBTRACTOR;
let sd_time = MINIMUM_DATE;
if (startDate && startDate !== "" && typeof startDate === 'object') {
sd_time = new Date(startDate).getTime();
if (sd_time >= sd) {
sd_time = sd;
}
}
let ed_time = MAXIMUM_DATE;
if (endDate && endDate !== "" && typeof endDate === 'object') {
ed_time = new Date(endDate).getTime();
}
if (!_limit && _limit === "" && typeof _limit !== 'number' && Math.round(_limit) !== _limit) {
_limit = 25;
}
if (!_offset && _offset === "" && typeof _offset !== 'number' && Math.round(_offset) !== _offset) {
_offset = 0
}
if (!_sortOrder && _sortOrder === "" && typeof _sortOrder !== 'number' && Math.round(_sortOrder) !== _sortOrder) {
_sortOrder = SORT_BY_SCORE;
}
const returnedResult = libSymphonySearch.symSESearch(this.indexFolderName, this.realTimeIndex, q, sd_time.toString(), ed_time.toString(), _offset, _limit, _sortOrder);
try {
let ret = returnedResult.readCString();
resolve(JSON.parse(ret));
} finally {
libSymphonySearch.symSEFreeResult(returnedResult);
}
});
}
static constructQuery(query, senderId, threadId) {
let q = "";
let tokens = query.toLowerCase()
.trim()
.replace(INVALID_CHARACTERS_REGEX, ' ')
.split(' ');
let hasToken = false;
let hashCashTagQuery = "(";
tokens.forEach((item, i) => {
if (i > 0 && (item.startsWith('#') || item.startsWith('$'))) {
hashCashTagQuery += " OR ";
}
if (item.startsWith('#') || item.startsWith('$')) {
hashCashTagQuery += ("tags:\"" + item + "\"");
hasToken = true;
} else {
q += item + " ";
}
});
hashCashTagQuery += ")";
if (q.replace(/ /g, "").length > 0 && hasToken) {
q += " OR ";
}
if (tokens.length > 0 && hasToken) {
q += hashCashTagQuery;
}
if (senderId && senderId !== "" && senderId.replace(/ /g, "").length > 0) {
q += ` AND (senderId: ${senderId})`;
}
if (threadId && threadId !== "" && threadId.replace(/ /g, "").length > 0) {
q += ` AND (threadId: ${threadId})`;
}
return q;
}
static indexValidator(file) {
let data;
let result = childProcess.execFileSync(INDEX_VALIDATOR, [file]).toString();
try {
data = JSON.parse(result);
if (data.status === 'OK') {
return data;
}
return new Error('Unable validate index folder')
} catch (err) {
throw (err);
}
}
}
module.exports = {
Search: Search
};

View File

@ -0,0 +1,76 @@
'use strict';
const ffi = require('ffi');
const ref = require('ref');
const electron = require('electron');
const app = electron.app;
const path = require('path');
const isDevEnv = require('../utils/misc.js').isDevEnv;
const isMac = require('../utils/misc.js').isMac;
const symLucyIndexer = ref.types.void;
const symLucyIndexerPtr = ref.refType(symLucyIndexer);
const execPath = path.dirname(app.getPath('exe'));
const winArchPath = process.arch === 'ia32' ? 'library/libsymphonysearch-x86.dll' : 'library/libsymphonysearch-x64.dll';
const rootPath = isMac ? 'library/libsymphonysearch.dylib' : winArchPath;
const productionPath = path.join(execPath, isMac ? '..' : '', rootPath);
const devPath = path.join(__dirname, '..', '..', rootPath);
const libraryPath = isDevEnv ? devPath : productionPath;
let libSymphonySearch = ffi.Library(libraryPath, {
//init
'symSE_init': ['void', []],
'symSE_remove_folder': ['int', ['string']],
'symSE_ensure_index_exists': ['int', ['string']],
'symSE_ensure_folder_exists': ['int', ['string']],
//first time indexing and delta indexing
'symSE_get_indexer': [symLucyIndexerPtr, ['string']], //will be removed
'symSE_create_partial_index': ['int', ['string', 'string', 'string']],
'symSE_merge_partial_index': ['int', ['string', 'string']],
//real time indexing
'symSE_index_realtime': ['int', ['string', 'string']],
'symSE_merge_temp_index': ['int', ['string', 'string']],
'symSE_clear_temp_index': ['int', ['string']],
//Search,
'symSE_search': ['char *', ['string', 'string', 'string', 'string', 'string', 'int', 'int', 'int']],
//Deletion
'symSE_delete_messages': ['int', ['string', 'string', 'string', 'string']],
//Index commit/optimize
'symSE_commit_index': ['int', [symLucyIndexerPtr, 'int']], //will be removed
//freePointer
'symSE_free_results': ['int', ['char *']]
});
module.exports = {
symSEInit: libSymphonySearch.symSE_init,
symSERemoveFolder: libSymphonySearch.symSE_remove_folder,
symSEEnsureIndexExists: libSymphonySearch.symSE_ensure_index_exists,
symSEEnsureFolderExists: libSymphonySearch.symSE_ensure_folder_exists,
symSEGetIndexer: libSymphonySearch.symSE_get_indexer,
symSECreatePartialIndex: libSymphonySearch.symSE_create_partial_index,
symSEMergePartialIndex: libSymphonySearch.symSE_merge_partial_index,
symSEIndexRealTime: libSymphonySearch.symSE_index_realtime,
symSEMergeTempIndex: libSymphonySearch.symSE_merge_temp_index,
symSEClearTempIndex: libSymphonySearch.symSE_clear_temp_index,
symSESearch: libSymphonySearch.symSE_search,
symSEDeleteMessages: libSymphonySearch.symSE_delete_messages,
symSECommitIndex: libSymphonySearch.symSE_commit_index,
symSEFreeResult: libSymphonySearch.symSE_free_results,
symSEInitAsync: libSymphonySearch.symSE_init.async,
symSERemoveFolderAsync: libSymphonySearch.symSE_remove_folder.async,
symSEEnsureIndexExistsAsync: libSymphonySearch.symSE_ensure_index_exists.async,
symSEEnsureFolderExistsAsync: libSymphonySearch.symSE_ensure_folder_exists.async,
symSEGetIndexerAsync: libSymphonySearch.symSE_get_indexer.async,
symSECreatePartialIndexAsync: libSymphonySearch.symSE_create_partial_index.async,
symSEMergePartialIndexAsync: libSymphonySearch.symSE_merge_partial_index.async,
symSEIndexRealTimeAsync: libSymphonySearch.symSE_index_realtime.async,
symSEMergeTempIndexAsync: libSymphonySearch.symSE_merge_temp_index.async,
symSEClearTempIndexAsync: libSymphonySearch.symSE_clear_temp_index.async,
symSESearchAsync: libSymphonySearch.symSE_search.async,
symSEDeleteMessagesAsync: libSymphonySearch.symSE_delete_messages.async,
symSECommitIndexAsync: libSymphonySearch.symSE_commit_index.async,
symSEFreeResultAsync: libSymphonySearch.symSE_free_results.async
};

BIN
library/indexvalidator-x64.exe Executable file

Binary file not shown.

BIN
library/indexvalidator-x86.exe Executable file

Binary file not shown.

BIN
library/indexvalidator.exec Executable file

Binary file not shown.

BIN
library/libsymphonysearch-x64.dll Executable file

Binary file not shown.

BIN
library/libsymphonysearch-x86.dll Executable file

Binary file not shown.

BIN
library/libsymphonysearch.dylib Executable file

Binary file not shown.

View File

@ -9,10 +9,12 @@
"dev": "npm run prebuild && cross-env ELECTRON_DEV=true electron .",
"demo-win": "npm run prebuild && cross-env ELECTRON_DEV=true electron . --url=file:///demo/index.html",
"demo-mac": "npm run prebuild && cross-env ELECTRON_DEV=true electron . --url=file://$(pwd)/demo/index.html",
"search-win": "npm run prebuild && cross-env ELECTRON_DEV=true electron . --url=file:///demo/search.html",
"search-mac": "npm run prebuild && cross-env ELECTRON_DEV=true electron . --url=file://$(pwd)/demo/search.html",
"unpacked-mac": "npm run prebuild && npm run test && build --mac --dir",
"packed-mac": "npm run unpacked-mac && packagesbuild -v installer/mac/symphony-mac-packager.pkgproj",
"unpacked-win": "npm run prebuild && npm run test && build --win --x64 --dir",
"unpacked-win-x86": "npm run prebuild && npm run test && build --win --ia32",
"unpacked-win-x86": "npm run prebuild && npm run test && build --win --ia32 --dir",
"prebuild": "npm run rebuild && npm run browserify-preload",
"browserify-preload": "browserify -o js/preload/_preloadMain.js -x electron --insert-global-vars=__filename,__dirname js/preload/preloadMain.js",
"rebuild": "electron-rebuild -f",
@ -31,7 +33,11 @@
"!installer/*",
"!tests/*"
],
"extraFiles": "config/Symphony.config",
"extraFiles": [
"config/Symphony.config",
"library/libsymphonysearch.dylib",
"library/indexvalidator.exec"
],
"appId": "symphony-electron-desktop",
"mac": {
"target": "dmg",
@ -94,8 +100,11 @@
"electron-context-menu": "^0.8.0",
"electron-dl": "^1.9.0",
"electron-squirrel-startup": "^1.0.0",
"ffi": "^2.2.0",
"filesize": "^3.5.10",
"keymirror": "0.1.1",
"randomstring": "^1.1.5",
"ref": "^1.3.4",
"winreg": "^1.2.3"
},
"optionalDependencies": {