UNPKG

vrem

Version:

An open-source automatic time-tracker

155 lines (154 loc) 6.91 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const http_1 = require("http"); const tracker_types_1 = require("./tracker_types"); const ipc_1 = require("../ipc"); const constants_1 = __importDefault(require("../constants")); const ipc_2 = require("../ipc"); const fs_1 = __importDefault(require("fs")); const tracker_utils_1 = require("./tracker_utils"); const { getActiveProgram, getIdleTime } = require('../../dist_native/vrem_windows.node'); const PORT = 3211; function startHttpServer() { const server = (0, http_1.createServer)(async (req, res) => { try { if (req.url === '/' && req.method === 'POST' && req.headers["content-type"] === 'application/json') { const chunks = []; for await (const chunk of req) chunks.push(chunk); if (!req.complete) return; const string = Buffer.concat(chunks).toString('utf8'); const data = JSON.parse(string); main(data); } res.writeHead(200).end(); } catch (e) { try { res.writeHead(500).end(); } catch (e) { } tracker_utils_1.dev && console.error(e); } }); server.listen(PORT, () => { console.info("Vrem's tracking process is listening on port ", PORT); }); } let subscriber = null; function startIpcServer() { const server = new ipc_2.IpcServer(); // server.command('subprogram', payload => { // main(payload); // return true; // }); server.command('subscribe', (payload, socket) => { subscriber = (0, ipc_1.createSequentialSocket)(socket); void subscriber.send(lastProgram); socket.on('close', () => { subscriber = null; }); socket.on('error', () => { }); // ignore errors }); server.listen(constants_1.default.autoTrackerSocketPath, () => { console.info("Vrem's tracking process is listening on socket ", constants_1.default.autoTrackerSocketPath); }); } // Set onExit callbacks to add the last entry to the log file { const exit = () => process.exit(); process.on('SIGINT', exit); process.on('SIGTERM', exit); const exceptionHandler = e => { tracker_utils_1.dev && console.error(e); fs_1.default.appendFileSync(constants_1.default.appFolder + '/tracker_errors.log', `\n${new Date()}\n${e.stack}\n`, 'utf8'); process.exit(1); }; process.on('uncaughtException', exceptionHandler); process.on('unhandledRejection', exceptionHandler); startIpcServer(); startHttpServer(); (0, tracker_utils_1.saveCurrentProgramToLogs)(); (0, tracker_utils_1.addToLogs)({ begin: true, timestamp: Date.now() }); process.on('exit', () => { (0, tracker_utils_1.addToLogs)({ end: true, timestamp: Date.now() }); tracker_utils_1.dev && console.log('Exit'); }); } let lastProgram = null; let lastSubprogramTimestamp = null; // deferredProgram can be only a browser. If the user switches to another program, // the tracker forgets the subprogram at once. deferredProgram makes sense when the extension is disabled, // but the browser remains in focus. let deferredProgram = null; let isIdle = false; const IDLE_THRESHOLD = 90000; const SUBPROGRAM_TIMEOUT = 2000; const MAIN_INTERVAL = 1000; function main(subprogramData = null) { const idleTime = getIdleTime(); tracker_utils_1.dev && console.log('Idle time = ', getIdleTime()); if (idleTime > IDLE_THRESHOLD) { if (!isIdle) { (0, tracker_utils_1.addToLogs)({ idle: true, timestamp: Date.now() }); isIdle = true; lastProgram = null; } return; } else if (isIdle) { isIdle = false; } const activeProgram = getActiveProgram(); if (!activeProgram || activeProgram.error) return; activeProgram.timestamp = Date.now(); function processProgram(program) { if (!lastProgram || lastProgram.path !== program.path || (0, tracker_types_1.isSubprogram)(lastProgram) !== (0, tracker_types_1.isSubprogram)(program)) { (0, tracker_utils_1.addToLogs)(program); lastProgram = program; subscriber && subscriber.send(lastProgram); } else if (program.timestamp - (lastProgram.lastActiveTimestamp || lastProgram.timestamp) > 9999) { lastProgram.lastActiveTimestamp = program.timestamp; (0, tracker_utils_1.updateCurrentProgramLastActiveTimestamp)(lastProgram.lastActiveTimestamp); } } if (subprogramData) { // when request came from the browser extension const subprogram = { ...subprogramData, description: '', parent: activeProgram }; lastSubprogramTimestamp = subprogramData.timestamp; if (!subprogram.path // extension send the last message with null values, when there is no focused website. // When subprogram changed parent.path it can be that there are two browsers, // but also that the user has switch to another program. We assume the latter here. || ((0, tracker_types_1.isSubprogram)(lastProgram) && lastProgram.path === subprogram.path && lastProgram.parent.path !== subprogram.parent.path)) { tracker_utils_1.dev && console.log('Turn off subprogram mode', subprogram); lastSubprogramTimestamp = null; } else { if (activeProgram.timestamp - subprogram.timestamp < 100) { //dev && console.log('timestamp diff', activeProgram.timestamp - subprogram.timestamp); processProgram(subprogram); deferredProgram = null; } return; } } if ((0, tracker_types_1.isSubprogram)(lastProgram) && lastSubprogramTimestamp) { // usual iteration if ((Date.now() - lastSubprogramTimestamp > SUBPROGRAM_TIMEOUT) || lastProgram.parent.path !== activeProgram.path) { tracker_utils_1.dev && console.log(`Switch to usual mode ${Date.now() - lastSubprogramTimestamp > SUBPROGRAM_TIMEOUT ? ' due to timeout' : 'due to program change.'}` + 'The deferred: ', deferredProgram); deferredProgram && processProgram(deferredProgram); deferredProgram = null; } else { deferredProgram = deferredProgram || activeProgram; // we should preserve the oldest timestamp return; } } processProgram(activeProgram); } setInterval(main, MAIN_INTERVAL);