Compare commits
10 commits
918b2d74fa
...
ab70ed3414
Author | SHA1 | Date | |
---|---|---|---|
ab70ed3414 | |||
746b39e1e8 | |||
9d52b870d4 | |||
bb1cca0433 | |||
c13b123423 | |||
eccbc863b3 | |||
d21e9ef018 | |||
842c432aa3 | |||
e408c07387 | |||
d75a18c192 |
9 changed files with 181 additions and 105 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -1,2 +1,3 @@
|
||||||
|
config.json
|
||||||
node_modules/
|
node_modules/
|
||||||
yarn.lock
|
npm-debug.log
|
||||||
|
|
4
.vscode/launch.json
vendored
4
.vscode/launch.json
vendored
|
@ -10,7 +10,9 @@
|
||||||
"<node_internals>/**"
|
"<node_internals>/**"
|
||||||
],
|
],
|
||||||
"program": "${workspaceFolder}/ninwa.js",
|
"program": "${workspaceFolder}/ninwa.js",
|
||||||
"args": []
|
"args": [
|
||||||
|
"example_config.json"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
20
LICENSE.md
Normal file
20
LICENSE.md
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
# MIT License
|
||||||
|
**Copyright (c) 2022 Daniel Sommer \<daniel.sommer@velvettear.de\>**
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is furnished
|
||||||
|
to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice (including the next
|
||||||
|
paragraph) shall be included in all copies or substantial portions of the
|
||||||
|
Software.
|
||||||
|
|
||||||
|
**THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
|
||||||
|
OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
|
||||||
|
OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.**
|
14
README.md
14
README.md
|
@ -46,13 +46,17 @@ node input watcher
|
||||||
- reload systemd-services
|
- reload systemd-services
|
||||||
`systemctl daemon-reload`
|
`systemctl daemon-reload`
|
||||||
|
|
||||||
- enable and start the ninwa as a systemd-service
|
- enable and start ninwa as a systemd-service
|
||||||
`systemctl enable --now ninwa`
|
`systemctl enable --now ninwa`
|
||||||
|
|
||||||
## configuration
|
## configuration
|
||||||
|
|
||||||
configuration is done entirely within the file `config.json`.
|
configuration is done entirely within the file `config.json`.
|
||||||
|
|
||||||
|
### server: [*object*]
|
||||||
|
- address: [*string*] server address to listen on (`0.0.0.0` to listen on all interfaces)
|
||||||
|
- port: [*number*] port to listen on
|
||||||
|
|
||||||
### log: [*object*]
|
### log: [*object*]
|
||||||
- level: [*string*] verbosity of the log; either `debug`, `info`, `warning` or `error`
|
- level: [*string*] verbosity of the log; either `debug`, `info`, `warning` or `error`
|
||||||
- timestamp: [*string*] format string for the timestamp; review [moment.js](https://momentjs.com/docs/#/displaying/format/) for further information
|
- timestamp: [*string*] format string for the timestamp; review [moment.js](https://momentjs.com/docs/#/displaying/format/) for further information
|
||||||
|
@ -77,4 +81,10 @@ configuration is done entirely within the file `config.json`.
|
||||||
- *name*: [*object*]
|
- *name*: [*object*]
|
||||||
- cmd: [*string*] command / path to script to execute
|
- cmd: [*string*] command / path to script to execute
|
||||||
- args: [*string-array*] arguments to pass to the executed command
|
- args: [*string-array*] arguments to pass to the executed command
|
||||||
- sudo: [*boolean*] use sudo to execute the command
|
- sudo: [*boolean*] use sudo to execute the command
|
||||||
|
|
||||||
|
**note:**
|
||||||
|
if you intend to use ninwa as a systemd-service with `sudo` make sure the configured user is allowed to execute the command without entering a password. **otherwise your service will just stop at the password prompt!**
|
||||||
|
|
||||||
|
- `sudo visudo`
|
||||||
|
- `username ALL=(ALL) NOPASSWD: command`
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
"timestamp": "DD.MM.YYYY HH:mm:ss:SS"
|
"timestamp": "DD.MM.YYYY HH:mm:ss:SS"
|
||||||
},
|
},
|
||||||
"combos": {
|
"combos": {
|
||||||
"delay": 5000
|
"timeout": 5000
|
||||||
},
|
},
|
||||||
"watchers": [
|
"watchers": [
|
||||||
{
|
{
|
||||||
|
@ -15,25 +15,31 @@
|
||||||
{
|
{
|
||||||
"key": "key_f1",
|
"key": "key_f1",
|
||||||
"combo": [
|
"combo": [
|
||||||
"key_f2",
|
"key_f5"
|
||||||
"key_f4"
|
|
||||||
],
|
],
|
||||||
"event": "EV_KEY",
|
"event": "EV_KEY",
|
||||||
"type": "keydown",
|
"type": "keydown",
|
||||||
"delay": 1000,
|
|
||||||
"command": "combo"
|
"command": "combo"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"key": "key_f1",
|
"key": "key_f1",
|
||||||
"combo": [
|
"combo": [
|
||||||
"key_f1",
|
"key_f6"
|
||||||
"key_f2"
|
|
||||||
],
|
],
|
||||||
"event": "EV_KEY",
|
"event": "EV_KEY",
|
||||||
"type": "keydown",
|
"type": "keydown",
|
||||||
"delay": 1000,
|
|
||||||
"command": "combo2"
|
"command": "combo2"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"key": "key_f2",
|
||||||
|
"combo": [
|
||||||
|
"key_f5",
|
||||||
|
"key_f6"
|
||||||
|
],
|
||||||
|
"event": "EV_KEY",
|
||||||
|
"type": "keydown",
|
||||||
|
"command": "combo3"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"key": "key_enter",
|
"key": "key_enter",
|
||||||
"type": "keydown",
|
"type": "keydown",
|
||||||
|
@ -73,6 +79,14 @@
|
||||||
],
|
],
|
||||||
"sudo": false
|
"sudo": false
|
||||||
},
|
},
|
||||||
|
"combo3": {
|
||||||
|
"cmd": "notify-send",
|
||||||
|
"args": [
|
||||||
|
"combo #3",
|
||||||
|
"third combo"
|
||||||
|
],
|
||||||
|
"sudo": false
|
||||||
|
},
|
||||||
"example": {
|
"example": {
|
||||||
"cmd": "notify-send",
|
"cmd": "notify-send",
|
||||||
"args": [
|
"args": [
|
||||||
|
@ -94,7 +108,6 @@
|
||||||
"args": [
|
"args": [
|
||||||
"https://velvettear.de"
|
"https://velvettear.de"
|
||||||
]
|
]
|
||||||
},
|
}
|
||||||
"sudo": false
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,5 +1,4 @@
|
||||||
const comboConfig = require('../config.json').combos;
|
const logger = require('./logger.js');
|
||||||
const commandConfig = require('../config.json').commands;
|
|
||||||
|
|
||||||
const LINE_START = 'Event: time';
|
const LINE_START = 'Event: time';
|
||||||
|
|
||||||
|
@ -13,16 +12,21 @@ class Keyfilter {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.actions = new Map();
|
this.actions = new Map();
|
||||||
|
this.registered = {
|
||||||
|
keys: [],
|
||||||
|
events: [],
|
||||||
|
types: []
|
||||||
|
}
|
||||||
for (let index = 0; index < config.length; index++) {
|
for (let index = 0; index < config.length; index++) {
|
||||||
this.setAction(config[index]);
|
this.registerAction(config[index]);
|
||||||
}
|
}
|
||||||
this.currentCombo = undefined;
|
this.currentCombo = undefined;
|
||||||
}
|
}
|
||||||
getCommand(command) {
|
getCommand(command) {
|
||||||
if (command === undefined || commandConfig === undefined) {
|
if (command === undefined || global.config?.commands === undefined) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const result = commandConfig[command];
|
const result = global.config.commands[command];
|
||||||
if (result === undefined) {
|
if (result === undefined) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -52,13 +56,17 @@ class Keyfilter {
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
setAction(config) {
|
registerAction(config) {
|
||||||
let key = config.key.toUpperCase();
|
let key = config.key.toUpperCase();
|
||||||
if (config.combo !== undefined && config.combo.length > 0) {
|
if (config.combo !== undefined && config.combo.length > 0) {
|
||||||
const tmp = JSON.parse(JSON.stringify(config.combo));
|
const tmp = JSON.parse(JSON.stringify(config.combo));
|
||||||
tmp.unshift(config.key);
|
tmp.unshift(config.key);
|
||||||
key = tmp.toString().toUpperCase();
|
key = tmp.toString().toUpperCase();
|
||||||
}
|
}
|
||||||
|
if (Array.from(this.actions.keys()).includes(key)) {
|
||||||
|
logger.warn('skipping already registered key(s) \'' + key + '\'...');
|
||||||
|
return;
|
||||||
|
}
|
||||||
this.actions.set(key,
|
this.actions.set(key,
|
||||||
{
|
{
|
||||||
type: this.getActionType(config.type),
|
type: this.getActionType(config.type),
|
||||||
|
@ -73,57 +81,70 @@ class Keyfilter {
|
||||||
}(),
|
}(),
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
const singleKeys = key.split(',');
|
||||||
|
for (let index = 0; index < singleKeys.length; index++) {
|
||||||
|
const singleKey = singleKeys[index];
|
||||||
|
if (!this.registered.keys.includes(singleKey)) {
|
||||||
|
this.registered.keys.push(singleKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!this.registered.events.includes(this.actions.get(key).event)) {
|
||||||
|
this.registered.events.push(this.actions.get(key).event);
|
||||||
|
}
|
||||||
|
if (!this.registered.types.includes(this.actions.get(key).type.id)) {
|
||||||
|
this.registered.types.push(this.actions.get(key).type.id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
filter(input) {
|
filter(input) {
|
||||||
if (input === undefined || input.length === 0) {
|
if (input === undefined || input.length === 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
input = input.toString();
|
const parsedEvent = this.parseLine(input);
|
||||||
let lines = input.split("\n");
|
if (this.parsedEventIsUnknown(parsedEvent)) {
|
||||||
for (let index = 0; index < lines.length; index++) {
|
return;
|
||||||
let line = lines[index];
|
}
|
||||||
if (line.length === 0) {
|
if (this.isPartOfCombo(parsedEvent)) {
|
||||||
|
if (parsedEvent.ignore) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return this.setComboResult(this.getFilterResult(parsedEvent.key, parsedEvent.type.action));
|
||||||
|
}
|
||||||
|
if (this.isStartOfCombo(parsedEvent)) {
|
||||||
|
return this.setComboResult(this.getFilterResult(parsedEvent.key, parsedEvent.type.action));
|
||||||
|
}
|
||||||
|
for (let [key, event] of this.actions) {
|
||||||
|
if (!this.parsedEventIsValid(key, event, parsedEvent)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!line.startsWith(LINE_START)) {
|
const result = this.getFilterResult(parsedEvent.key, event.type.action, event.command);
|
||||||
continue;
|
if (this.shouldBeDelayed(event)) {
|
||||||
}
|
result.delayed = true;
|
||||||
const parsedEvent = this.parseLine(line);
|
return result;
|
||||||
if (parsedEvent === undefined) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
for (let [key, event] of this.actions) {
|
|
||||||
if (this.currentCombo === undefined && !this.isParsedEventValid(key, event, parsedEvent)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (this.isStartOfCombo(parsedEvent)) {
|
|
||||||
return this.setComboResult(this.getFilterResult(parsedEvent.key, parsedEvent.type.action));
|
|
||||||
}
|
|
||||||
if (this.isPartOfCombo(parsedEvent)) {
|
|
||||||
if (parsedEvent.ignore) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
return this.setComboResult(this.getFilterResult(parsedEvent.key, parsedEvent.type.action));
|
|
||||||
}
|
|
||||||
if (!this.isParsedEventValid(key, event, parsedEvent)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (this.shouldBeDelayed(event)) {
|
|
||||||
const result = this.getFilterResult(parsedEvent.key, event.type.action, event.command);
|
|
||||||
result.delayed = true;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
event.captured = new Date().getTime();
|
|
||||||
return this.getFilterResult(parsedEvent.key, event.type.action, event.command);
|
|
||||||
}
|
}
|
||||||
|
event.captured = new Date().getTime();
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
isParsedEventValid(key, value, parsed) {
|
parsedEventIsUnknown(parsedEvent) {
|
||||||
let keyCheck = key === parsed.key;
|
return parsedEvent === undefined || !this.registered.keys.includes(parsedEvent.key) || !this.registered.events.includes(parsedEvent.event) || !this.registered.types.includes(parsedEvent.type.id);
|
||||||
if (value.combo !== undefined && value.combo.length > 0) {
|
}
|
||||||
keyCheck = key.includes(parsed.key);
|
parsedEventIsValid(key, value, parsed) {
|
||||||
|
if (value.event !== parsed.event || value.type.id !== parsed.type.id) {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
return keyCheck && (value.event === undefined || value.event === parsed.event) && value.type.id === parsed.type.id;
|
if (value.combo === undefined || value.combo.length === 0) {
|
||||||
|
return key === parsed.key;
|
||||||
|
}
|
||||||
|
if (this.currentCombo === undefined) {
|
||||||
|
return key.startsWith(parsed.key);
|
||||||
|
}
|
||||||
|
for (let index = 0; index < this.currentCombo.possibilities.length; index++) {
|
||||||
|
if (this.currentCombo.possibilities[index].combo[0].toUpperCase() === parsed.key) {
|
||||||
|
this.resetCurrentCombo();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
setComboResult(result) {
|
setComboResult(result) {
|
||||||
if (result === undefined || this.currentCombo === undefined) {
|
if (result === undefined || this.currentCombo === undefined) {
|
||||||
|
@ -151,6 +172,9 @@ class Keyfilter {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
parseLine(line) {
|
parseLine(line) {
|
||||||
|
if (line === undefined || line.length === 0 || !line.startsWith(LINE_START)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
const parts = line.split(',');
|
const parts = line.split(',');
|
||||||
const event = parts[1].substring(parts[1].indexOf('(') + 1, parts[1].lastIndexOf(')'));
|
const event = parts[1].substring(parts[1].indexOf('(') + 1, parts[1].lastIndexOf(')'));
|
||||||
|
@ -168,15 +192,12 @@ class Keyfilter {
|
||||||
return new Date().getTime() - event.captured < event.delay;
|
return new Date().getTime() - event.captured < event.delay;
|
||||||
}
|
}
|
||||||
isStartOfCombo(parsedEvent) {
|
isStartOfCombo(parsedEvent) {
|
||||||
if (this.currentCombo !== undefined) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
let possibilities = [];
|
let possibilities = [];
|
||||||
for (let [actionKey, actionEvent] of this.actions) {
|
for (let [actionKey, actionEvent] of this.actions) {
|
||||||
if (actionEvent.combo === undefined || actionEvent.combo.length === 0) {
|
if (actionEvent.combo === undefined || actionEvent.combo.length === 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!actionKey.toUpperCase().startsWith(parsedEvent.key)) {
|
if (!actionKey.toUpperCase().startsWith(parsedEvent.key) || actionEvent.type.id !== parsedEvent.type.id || actionEvent.event !== parsedEvent.event) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
possibilities.push(JSON.parse(JSON.stringify(actionEvent)));
|
possibilities.push(JSON.parse(JSON.stringify(actionEvent)));
|
||||||
|
@ -192,24 +213,18 @@ class Keyfilter {
|
||||||
done: [parsedEvent.key],
|
done: [parsedEvent.key],
|
||||||
possibilities: possibilities
|
possibilities: possibilities
|
||||||
};
|
};
|
||||||
|
this.setComboTimeout();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
isPartOfCombo(parsedEvent) {
|
isPartOfCombo(parsedEvent) {
|
||||||
if (this.hasComboTimedOut()) {
|
|
||||||
this.resetCurrentCombo();
|
|
||||||
}
|
|
||||||
if (this.currentCombo === undefined || this.currentCombo.type.id !== parsedEvent.type.id || this.currentCombo.event !== parsedEvent.event) {
|
if (this.currentCombo === undefined || this.currentCombo.type.id !== parsedEvent.type.id || this.currentCombo.event !== parsedEvent.event) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// if (this.currentCombo.done.includes(parsedEvent.key)) {
|
|
||||||
// parsedEvent.ignore = true;
|
|
||||||
// return true;
|
|
||||||
// }
|
|
||||||
let possibilities = [];
|
let possibilities = [];
|
||||||
for (let index = 0; index < this.currentCombo.possibilities.length; index++) {
|
for (let index = 0; index < this.currentCombo.possibilities.length; index++) {
|
||||||
const possibility = this.currentCombo.possibilities[index];
|
const possibility = this.currentCombo.possibilities[index];
|
||||||
if (possibility.combo.length === 0) {
|
if (possibility.combo.length === 0) {
|
||||||
break;
|
continue;
|
||||||
}
|
}
|
||||||
if (possibility.combo[0].toUpperCase() !== parsedEvent.key) {
|
if (possibility.combo[0].toUpperCase() !== parsedEvent.key) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -232,17 +247,29 @@ class Keyfilter {
|
||||||
tmp.done = this.currentCombo.done;
|
tmp.done = this.currentCombo.done;
|
||||||
this.currentCombo = tmp;
|
this.currentCombo = tmp;
|
||||||
}
|
}
|
||||||
|
this.setComboTimeout();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
hasComboTimedOut() {
|
setComboTimeout() {
|
||||||
return false;
|
if (this.currentCombo === undefined || global.config?.combos?.timeout === undefined || isNaN(global.config?.combos?.timeout)) {
|
||||||
return comboConfig !== undefined &&
|
return;
|
||||||
comboConfig.delay !== undefined &&
|
}
|
||||||
this.currentCombo !== undefined &&
|
this.clearComboTimeout();
|
||||||
this.currentCombo.timestamp !== undefined &&
|
logger.debug('setting timeout for current combo to ' + parseInt(global.config.combos.timeout) + 'ms');
|
||||||
new Date().getTime() - this.currentCombo.timestamp > comboConfig.delay;
|
this.comboTimeout = setTimeout(() => {
|
||||||
|
this.resetCurrentCombo()
|
||||||
|
}, parseInt(global.config.combos.timeout));
|
||||||
|
}
|
||||||
|
clearComboTimeout() {
|
||||||
|
if (this.comboTimeout === undefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
logger.debug('clearing timeout for current combo');
|
||||||
|
clearTimeout(this.comboTimeout);
|
||||||
}
|
}
|
||||||
resetCurrentCombo() {
|
resetCurrentCombo() {
|
||||||
|
this.clearComboTimeout();
|
||||||
|
logger.debug('resetting current combo');
|
||||||
this.currentCombo = undefined;
|
this.currentCombo = undefined;
|
||||||
}
|
}
|
||||||
isValid() {
|
isValid() {
|
||||||
|
|
|
@ -62,30 +62,13 @@ class Watcher {
|
||||||
}
|
}
|
||||||
logger.debug('adding stdout listener to watcher \'' + this.device + '\'...');
|
logger.debug('adding stdout listener to watcher \'' + this.device + '\'...');
|
||||||
this.process.stdout.on('data', (data) => {
|
this.process.stdout.on('data', (data) => {
|
||||||
if (this.keyfilter == undefined) {
|
if (this.keyfilter === undefined) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let filtered = this.keyfilter.filter(data);
|
const lines = data.toString().split('\n');
|
||||||
if (filtered === undefined) {
|
for (let index = 0; index < lines.length; index++) {
|
||||||
return;
|
this.handleEvent(this.keyfilter.filter(lines[index]));
|
||||||
}
|
}
|
||||||
logger.debug('handling captured \'' + filtered.type + '\' event for key \'' + filtered.key + '\' from watcher \'' + this.device + '\'...');
|
|
||||||
if (filtered.delayed) {
|
|
||||||
logger.debug('delaying captured event...');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (filtered.combo) {
|
|
||||||
if (!filtered.combo.finished) {
|
|
||||||
logger.debug('captured event is part of ' + filtered.combo.possibilities + ' possible combo(s) and not yet finished')
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
logger.debug('captured event finished combo \'' + filtered.combo.done.toString().toUpperCase()+ '\'');
|
|
||||||
}
|
|
||||||
this.keyfilter.resetCurrentCombo();
|
|
||||||
logger.info('executing command \'' + filtered.command.name + '\' registered for captured event...');
|
|
||||||
cli.execute(filtered.command.cmd, filtered.command.args, filtered.command.sudo)
|
|
||||||
.then(logger.info)
|
|
||||||
.catch(logger.error);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
addStdErrListener() {
|
addStdErrListener() {
|
||||||
|
@ -155,5 +138,27 @@ class Watcher {
|
||||||
.catch(reject);
|
.catch(reject);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
handleEvent(event) {
|
||||||
|
if (event === undefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
logger.debug('handling captured \'' + event.type + '\' event for key \'' + event.key + '\' from watcher \'' + this.device + '\'...');
|
||||||
|
if (event.delayed) {
|
||||||
|
logger.debug('delaying captured event...');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (event.combo) {
|
||||||
|
if (!event.combo.finished) {
|
||||||
|
logger.debug('captured event is part of ' + event.combo.possibilities + ' possible combo(s) and not yet finished')
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
logger.debug('captured event finished combo \'' + event.combo.done.toString().toUpperCase() + '\'');
|
||||||
|
}
|
||||||
|
this.keyfilter.resetCurrentCombo();
|
||||||
|
logger.info('executing command \'' + event.command.name + '\' registered for captured event...');
|
||||||
|
cli.execute(event.command.cmd, event.command.args, event.command.sudo)
|
||||||
|
.then(logger.info)
|
||||||
|
.catch(logger.error);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
module.exports = Watcher;
|
module.exports = Watcher;
|
10
ninwa.js
10
ninwa.js
|
@ -5,24 +5,22 @@ const packageJSON = require('./package.json');
|
||||||
|
|
||||||
const INTERRUPTS = ['SIGINT', 'SIGTERM'];
|
const INTERRUPTS = ['SIGINT', 'SIGTERM'];
|
||||||
|
|
||||||
let config;
|
|
||||||
|
|
||||||
main();
|
main();
|
||||||
|
|
||||||
async function main() {
|
async function main() {
|
||||||
handleInterrupts();
|
handleInterrupts();
|
||||||
try {
|
try {
|
||||||
let configFile = await util.getFileInfo(process.argv[2] || __dirname + '/config.json');
|
let configFile = await util.getFileInfo(process.argv[2] || __dirname + '/config.json');
|
||||||
config = require(configFile.path);
|
global.config = require(configFile.path);
|
||||||
config.path = config.path;
|
global.config.path = configFile.path;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
logger.initialize(config.log.level, config.log.timestamp);
|
logger.initialize(global.config.log.level, global.config.log.timestamp);
|
||||||
logger.info(packageJSON.name + ' ' + packageJSON.version + ' starting...');
|
logger.info(packageJSON.name + ' ' + packageJSON.version + ' starting...');
|
||||||
await watchers.initialize(config.watchers);
|
await watchers.initialize(global.config.watchers);
|
||||||
await watchers.start();
|
await watchers.start();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
logger.error(err);
|
logger.error(err);
|
||||||
|
|
Loading…
Reference in a new issue