Use multi-part form to send files to index on desktop client

- Add typing for variables in for loop and other minor formatting clean-up
- Assume utf8 encoding for text files and binary for image, pdf files
This commit is contained in:
Debanjum Singh Solanky
2023-10-11 18:12:12 -07:00
parent 60e9a61647
commit 68018ef397

View File

@@ -8,7 +8,6 @@ const {dialog} = require('electron');
const cron = require('cron').CronJob; const cron = require('cron').CronJob;
const axios = require('axios'); const axios = require('axios');
const { Readable } = require('stream');
const KHOJ_URL = 'http://127.0.0.1:42110' const KHOJ_URL = 'http://127.0.0.1:42110'
@@ -65,7 +64,7 @@ const schema = {
var state = {} var state = {}
const store = new Store({schema}); const store = new Store({ schema });
console.log(store); console.log(store);
@@ -86,37 +85,48 @@ function handleSetTitle (event, title) {
}); });
} }
function filenameToMimeType (filename) {
const extension = filename.split('.').pop();
switch (extension) {
case 'pdf':
return 'application/pdf';
case 'png':
return 'image/png';
case 'jpg':
return 'image/jpeg';
case 'jpeg':
return 'image/jpeg';
case 'markdown':
return 'text/markdown';
case 'org':
return 'text/org';
default:
return 'text/plain';
}
}
function pushDataToKhoj (regenerate = false) { function pushDataToKhoj (regenerate = false) {
let filesToPush = []; let filesToPush = [];
const files = store.get('files'); const files = store.get('files') || [];
const folders = store.get('folders'); const folders = store.get('folders') || [];
state = { state = { completed: true }
completed: true
for (const file of files) {
filesToPush.push(file.path);
} }
if (files) { for (const folder of folders) {
for (file of files) { const files = fs.readdirSync(folder.path, { withFileTypes: true });
filesToPush.push(file.path); for (const file of files) {
} if (file.isFile() && validFileTypes.includes(file.name.split('.').pop())) {
} filesToPush.push(path.join(folder.path, file.name));
if (folders) {
for (folder of folders) {
const files = fs.readdirSync(folder.path, { withFileTypes: true });
for (file of files) {
if (file.isFile() && validFileTypes.includes(file.name.split('.').pop())) {
filesToPush.push(path.join(folder.path, file.name));
}
} }
} }
} }
let data = {
files: []
}
const lastSync = store.get('lastSync') || []; const lastSync = store.get('lastSync') || [];
const formData = new FormData();
for (file of filesToPush) { for (const file of filesToPush) {
const stats = fs.statSync(file); const stats = fs.statSync(file);
if (!regenerate) { if (!regenerate) {
if (stats.mtime.toISOString() < lastSync.find((syncedFile) => syncedFile.path === file)?.datetime) { if (stats.mtime.toISOString() < lastSync.find((syncedFile) => syncedFile.path === file)?.datetime) {
@@ -125,18 +135,10 @@ function pushDataToKhoj (regenerate = false) {
} }
try { try {
let rawData; encoding = binaryFileTypes.includes(file.split('.').pop()) ? "binary" : "utf8";
// If the file is a PDF or IMG file, read it as a binary file mimeType = filenameToMimeType(file) + (encoding === "utf8" ? "; charset=UTF-8" : "");
if (binaryFileTypes.includes(file.split('.').pop())) { fileObj = new Blob([fs.createReadStream(file, encoding)], { type: mimeType });
rawData = fs.readFileSync(file).toString('base64'); formData.append('files', fileObj, file);
} else {
rawData = fs.readFileSync(file, 'utf8');
}
data.files.push({
path: file,
content: rawData
});
state[file] = { state[file] = {
success: true, success: true,
} }
@@ -151,44 +153,37 @@ function pushDataToKhoj (regenerate = false) {
for (const syncedFile of lastSync) { for (const syncedFile of lastSync) {
if (!filesToPush.includes(syncedFile.path)) { if (!filesToPush.includes(syncedFile.path)) {
data.files.push({ fileObj = new Blob([""], { type: filenameToMimeType(syncedFile.path) });
path: syncedFile.path, formData.append('files', fileObj, syncedFile.path);
content: ""
});
} }
} }
const headers = { 'x-api-key': 'secret', 'Content-Type': 'application/json' }; if (!!formData?.entries()?.next().value) {
const hostURL = store.get('hostURL') || KHOJ_URL;
const stream = new Readable({ const headers = {
read() { 'x-api-key': 'secret'
this.push(JSON.stringify(data)); };
this.push(null); axios.post(`${hostURL}/api/v1/indexer/batch?regenerate=${regenerate}`, formData, { headers })
} .then(response => {
}); console.log(response.data);
const win = BrowserWindow.getAllWindows()[0];
const hostURL = store.get('hostURL') || KHOJ_URL; win.webContents.send('update-state', state);
let lastSync = [];
axios.post(`${hostURL}/api/v1/indexer/batch?regenerate=${regenerate}`, stream, { headers }) for (const file of filesToPush) {
.then(response => { lastSync.push({
console.log(response.data); path: file,
const win = BrowserWindow.getAllWindows()[0]; datetime: new Date().toISOString()
win.webContents.send('update-state', state); });
let lastSync = []; }
for (const file of filesToPush) { store.set('lastSync', lastSync);
lastSync.push({ })
path: file, .catch(error => {
datetime: new Date().toISOString() console.error(error);
}); state['completed'] = false
} const win = BrowserWindow.getAllWindows()[0];
store.set('lastSync', lastSync); win.webContents.send('update-state', state);
}) });
.catch(error => { }
console.error(error);
state['completed'] = false
const win = BrowserWindow.getAllWindows()[0];
win.webContents.send('update-state', state);
});
} }
pushDataToKhoj(); pushDataToKhoj();