nodehotkey
Version:
Authotkey like macros for NodeJS
292 lines • 14.3 kB
JavaScript
;
/*******************************************************************************************
* *
* ███╗ ██╗ ██████╗ ██████╗ ███████╗██╗ ██╗ ██████╗ ████████╗██╗ ██╗███████╗██╗ ██╗ *
* ████╗ ██║██╔═══██╗██╔══██╗██╔════╝██║ ██║██╔═══██╗╚══██╔══╝██║ ██╔╝██╔════╝╚██╗ ██╔╝ *
* ██╔██╗ ██║██║ ██║██║ ██║█████╗ ███████║██║ ██║ ██║ █████╔╝ █████╗ ╚████╔╝ *
* ██║╚██╗██║██║ ██║██║ ██║██╔══╝ ██╔══██║██║ ██║ ██║ ██╔═██╗ ██╔══╝ ╚██╔╝ *
* ██║ ╚████║╚██████╔╝██████╔╝███████╗██║ ██║╚██████╔╝ ██║ ██║ ██╗███████╗ ██║ *
* *
* Title: NodeHotKey *
* Author: Rubinder Singh *
* Date: 07-Jun-2019 *
*******************************************************************************************/
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
var KeyboardMouse_1 = require("../utils/KeyboardMouse");
var Keycodes_1 = require("../utils/Keycodes");
var Window_1 = require("../utils/Window");
var KeyCodeToPrintableChar_1 = require("./KeyCodeToPrintableChar");
var RunMacro_1 = require("./RunMacro");
// tslint:disable-next-line: no-var-requires
var EventEmitter = require('events');
var NodeHotKey = /** @class */ (function (_super) {
__extends(NodeHotKey, _super);
function NodeHotKey(pMacros) {
var _this = _super.call(this) || this;
var robot = require('robot-js');
var timer = robot.Timer();
var doubleKeyCodes = [160, 161, 162, 163, 164, 165];
var listeningInterval;
var macros;
var currHotstring;
var justRanMacro;
var isRobotOn;
var keyboardStatePrev;
var keyboardStateCurr;
var mouseStatePrev;
var mouseStateCurr;
var emptyMacrosObject = {
EmptyMacro: { steps: [] },
};
var eventTypes = {
hotKeyTriggered: 'hotKeyTriggered',
hotstringTriggered: 'hotstringTriggered',
keyPressed: 'keyPressed',
keyReleased: 'keyReleased',
loopTriggered: 'loopTriggered',
mouseKeyPressed: 'mouseKeyPressed',
mouseKeyReleased: 'mouseKeyReleased',
};
var emit = _this.emit.bind(_this);
var on = _this.on.bind(_this);
macros = pMacros || emptyMacrosObject;
listeningInterval = null;
currHotstring = '';
justRanMacro = false;
isRobotOn = false;
function checkRobotOn(keyCode) {
var timeElapsed = 0;
// if key is in exception list don't run the function and simply return false
// e.g. for Shift keycodes 16, 160 and 161 all are triggred together which may cause misleading results
if (doubleKeyCodes.indexOf(Number(keyCode)) !== -1) {
return false;
}
if (keyboardStatePrev[keyCode] !== keyboardStateCurr[keyCode]) {
if (timer.hasStarted()) {
timeElapsed = timer.getElapsed();
timer.reset();
}
timer.start();
if (process.env.NODE_ENV === 'dev') {
console.log('Timer elapsed:', timeElapsed);
}
if (timeElapsed < 10) {
// the keys are being pressed by robot
return true;
}
else {
// the keys are being pressed by human
return false;
}
}
return false;
}
function emitEvent(eventType, outConsole, eventData) {
emit(eventType, eventData);
if (process.env.NODE_ENV === 'dev') {
console.log(eventType + ':', outConsole);
}
}
function startLoops() {
Object.keys(macros).forEach(function (key) {
var macro = macros[key];
if (macro.loop) {
setInterval(function () {
if (matchMacroConditions(macro.conditions)) {
emitEvent(eventTypes.loopTriggered, key, {
loopInterval: macro.loop,
macroName: key,
});
RunMacro_1.runMacro(macro.steps);
}
}, macro.loop * 1000);
}
});
}
function isKeyPressed(keyStatePrev, keyStateCurr, keyCode) {
if (keyStatePrev[keyCode] === false && keyStateCurr[keyCode] === true) {
return true;
}
return false;
}
function isKeyReleased(keyStatePrev, keyStateCurr, keyCode) {
if (keyStatePrev[keyCode] === true && keyStateCurr[keyCode] === false) {
return true;
}
return false;
}
function keyboardPressReleaseEvents(keyStatePrev, keyStateCurr, keyCode) {
// key pressed
if (isKeyPressed(keyStatePrev, keyStateCurr, keyCode)) {
emitEvent(eventTypes.keyPressed, keyCode + " pressed", {
keyBoardState: keyStateCurr,
keyCode: keyCode,
printableChar: KeyCodeToPrintableChar_1.keyCodeToPrintableChar(Number(keyCode), keyStateCurr[Keycodes_1.KEYCODES._SHIFT]),
});
}
// key released
if (isKeyReleased(keyStatePrev, keyStateCurr, keyCode)) {
emitEvent(eventTypes.keyReleased, keyCode + " released", {
keyBoardState: keyStateCurr,
keyCode: keyCode,
printableChar: KeyCodeToPrintableChar_1.keyCodeToPrintableChar(Number(keyCode), keyStateCurr[Keycodes_1.KEYCODES._SHIFT]),
});
}
}
function mousePressReleaseEvents(keyStatePrev, keyStateCurr, keyCode) {
// key pressed
if (isKeyPressed(keyStatePrev, keyStateCurr, keyCode)) {
emitEvent(eventTypes.keyPressed, keyCode + " pressed", {
keyBoardState: keyStateCurr,
keyCode: keyCode,
printableChar: KeyCodeToPrintableChar_1.keyCodeToPrintableChar(Number(keyCode), keyStateCurr[Keycodes_1.KEYCODES._SHIFT]),
});
}
// key released
if (isKeyReleased(keyStatePrev, keyStateCurr, keyCode)) {
emitEvent(eventTypes.keyReleased, keyCode + " released", {
keyBoardState: keyStateCurr,
keyCode: keyCode,
printableChar: KeyCodeToPrintableChar_1.keyCodeToPrintableChar(Number(keyCode), keyStateCurr[Keycodes_1.KEYCODES._SHIFT]),
});
}
}
function matchMacroConditions(conditions) {
// if conditions are not specified always return true
if (conditions === undefined) {
return true;
}
// start matching all the conditions one by one
if (conditions.window && !Window_1.matchCurrentWindowTitle(conditions.window)) {
return false;
}
return true;
}
function detectHotKeyEvents() {
function areKeysPressed(keyCodeArr, keyState, mouseState) {
var keysArePressed = true;
keyCodeArr.forEach(function (keyCode) {
if (!keyState[keyCode] && !mouseState[keyCode]) {
keysArePressed = false;
}
});
return keysArePressed;
}
if (justRanMacro === false) {
Object.keys(macros).forEach(function (key) {
var macro = macros[key];
if (macro.hotkeys &&
areKeysPressed(macro.hotkeys, keyboardStateCurr, mouseStateCurr) &&
matchMacroConditions(macro.conditions)) {
emitEvent(eventTypes.hotKeyTriggered, "" + key, {
macroName: key,
});
justRanMacro = true;
setTimeout(function () {
justRanMacro = false;
}, 500);
doubleKeyCodes.forEach(function (keyCode) { return KeyboardMouse_1.releaseKey(keyCode); });
macro.hotkeys.forEach(function (keyCode) { return KeyboardMouse_1.releaseKey(keyCode); });
RunMacro_1.runMacro(macro.steps);
}
});
}
}
function detectHotstringEvents(keyCode, isShiftOn) {
// update currHotstring
var keyPressedCodeNumber = Number(keyCode);
var char = KeyCodeToPrintableChar_1.keyCodeToPrintableChar(keyPressedCodeNumber, isShiftOn);
// shift key is exception for hotstring capture
if (char === '' && keyPressedCodeNumber !== 16 && keyPressedCodeNumber !== 160 && keyPressedCodeNumber !== 161) {
currHotstring = '';
}
else {
currHotstring += char;
}
if (process.env.NODE_ENV === 'dev') {
console.log('Hostring recorded:', currHotstring);
}
// match currHotstring in macros
Object.keys(macros).forEach(function (key) {
var macro = macros[key];
if (macro.hotstring &&
macro.hotstring === currHotstring &&
matchMacroConditions(macro.conditions)) {
doubleKeyCodes.forEach(function (code) { KeyboardMouse_1.releaseKey(code); });
currHotstring = '';
if (macro.steps[0].type !== undefined || macro.steps[0].paste !== undefined) {
// tslint:disable-next-line:prefer-for-of
for (var i = 0; i < macro.hotstring.length; i++) {
KeyboardMouse_1.click(Keycodes_1.KEYCODES._BACKSPACE);
}
}
emitEvent(eventTypes.hotstringTriggered, macro.hotstring, {
hotString: macro.hotstring,
macroName: key,
});
RunMacro_1.runMacro(macro.steps);
}
});
}
function startListening() {
keyboardStatePrev = robot.Keyboard.getState();
mouseStatePrev = robot.Mouse.getState();
on(eventTypes.keyPressed, function (eventData) {
// Hotstrings
if (!isRobotOn) {
detectHotstringEvents(eventData.keyCode, eventData.keyBoardState[Keycodes_1.KEYCODES._SHIFT]);
}
else {
currHotstring = '';
}
});
// Loops
startLoops();
listeningInterval = setInterval(function () {
// keyboard
keyboardStateCurr = robot.Keyboard.getState();
Object.keys(keyboardStateCurr).forEach(function (keyCode) {
isRobotOn = checkRobotOn(keyCode);
keyboardPressReleaseEvents(keyboardStatePrev, keyboardStateCurr, keyCode);
});
keyboardStatePrev = keyboardStateCurr;
// Mouse
mouseStateCurr = robot.Mouse.getState();
Object.keys(mouseStateCurr).forEach(function (keyCode) {
mousePressReleaseEvents(mouseStateCurr, mouseStatePrev, keyCode);
});
mouseStatePrev = mouseStateCurr;
// Macros
if (!isRobotOn) {
// hotkeys
detectHotKeyEvents();
}
}, 0);
}
function stopListening() {
if (listeningInterval) {
clearInterval(listeningInterval);
}
}
_this.startListening = startListening;
_this.stopListening = stopListening;
_this.eventTypes = eventTypes;
return _this;
}
return NodeHotKey;
}(EventEmitter));
exports.NodeHotKey = NodeHotKey;
//# sourceMappingURL=NodeHotKey.js.map