ninwa/libs/keyfilter.js

226 lines
7.5 KiB
JavaScript
Raw Normal View History

2022-03-10 14:05:08 +01:00
const config = require('../config.json');
2022-03-03 03:35:34 +01:00
const LINE_START = 'Event: time';
2022-02-15 04:33:19 +01:00
const ACTION_KEYUP = { id: 0, action: 'keyup' };
const ACTION_KEYDOWN = { id: 1, action: 'keydown' };
const ACTION_KEYHOLD = { id: 2, action: 'keyhold' };
const VARIABLE_KEY = '{{ key }}';
const VARIABLE_TYPE = '{{ type }}';
2022-02-15 04:33:19 +01:00
class Keyfilter {
constructor(keys) {
if ((keys === undefined || keys.length === 0)) {
2022-02-15 04:33:19 +01:00
return;
}
this.actions = new Map();
for (let index = 0; index < keys.length; index++) {
2022-03-03 03:35:34 +01:00
this.setAction(keys[index]);
2022-02-15 04:33:19 +01:00
}
2022-03-03 03:35:34 +01:00
this.currentCombo = undefined;
2022-02-15 04:33:19 +01:00
}
2022-03-03 03:35:34 +01:00
setAction(config) {
let type = ACTION_KEYDOWN;
2022-03-03 03:35:34 +01:00
switch (config.type.toLowerCase()) {
case ACTION_KEYUP.action:
type = ACTION_KEYUP;
break;
case ACTION_KEYHOLD.action:
type = ACTION_KEYHOLD;
break;
2022-02-15 04:33:19 +01:00
}
let key = config.key.toUpperCase();
if (config.combo !== undefined && config.combo.length > 0) {
const tmp = JSON.parse(JSON.stringify(config.combo));
tmp.unshift(config.key);
key = tmp.toString().toUpperCase();
}
this.actions.set(key,
2022-03-03 03:35:34 +01:00
{
type: type,
event: config.event,
2022-03-10 14:05:08 +01:00
command: getCommand(config.command),
2022-03-03 03:35:34 +01:00
combo: config.combo,
delay: function () {
if (config.combo === undefined) {
return config.delay;
}
return config.delay || 1000;
}(),
}
);
2022-02-15 04:33:19 +01:00
}
filter(input) {
2022-03-03 03:35:34 +01:00
if (input === undefined || input.length === 0) {
2022-02-15 04:33:19 +01:00
return;
}
input = input.toString();
let lines = input.split("\n");
for (let index = 0; index < lines.length; index++) {
let line = lines[index];
2022-03-03 03:35:34 +01:00
if (line.length === 0) {
continue;
}
if (!line.startsWith(LINE_START)) {
2022-02-15 04:33:19 +01:00
continue;
}
2022-03-03 03:35:34 +01:00
const parsedEvent = this.parseLine(line);
if (parsedEvent === undefined) {
continue;
}
for (let [key, event] of this.actions) {
2022-03-03 03:35:34 +01:00
if (this.currentCombo === undefined && !this.isParsedEventValid(key, event, parsedEvent)) {
2022-02-15 04:33:19 +01:00
continue;
}
if (this.isStartOfCombo(key, event, parsedEvent)) {
2022-03-03 03:35:34 +01:00
return this.getFilterResult(key, event, 'combo', this.currentCombo);
}
if (this.isPartOfCombo(parsedEvent)) {
if (parsedEvent.ignore) {
continue;
}
const result = this.getFilterResult(key, event, 'combo', this.currentCombo);
if (this.currentCombo.finished) {
2022-03-03 03:35:34 +01:00
this.resetCurrentCombo();
}
return result;
}
if (!this.isParsedEventValid(key, event, parsedEvent)) {
2022-02-15 04:33:19 +01:00
continue;
}
2022-03-03 03:35:34 +01:00
if (this.shouldBeDelayed(event)) {
return this.getFilterResult(key, event, 'delayed', true);
2022-02-15 04:33:19 +01:00
}
2022-03-03 03:35:34 +01:00
event.captured = new Date().getTime();
return this.getFilterResult(key, event);
2022-02-15 04:33:19 +01:00
}
}
}
2022-03-03 03:35:34 +01:00
isParsedEventValid(key, value, parsed) {
let keyCheck = key === parsed.key;
if (value.combo !== undefined && value.combo.length > 0) {
keyCheck = key.includes(parsed.key);
}
return keyCheck && (value.event === undefined || value.event === parsed.event) && value.type.id === parsed.type;
2022-03-03 03:35:34 +01:00
}
getFilterResult(key, event, extraName, extra) {
if (key === undefined || event === undefined) {
return;
}
let result = {
key: key,
type: event.type.action,
command: event.command,
delay: event.delay
};
2022-03-03 03:35:34 +01:00
if (extraName !== undefined && extra !== undefined) {
result[extraName] = extra;
}
return result;
}
parseLine(line) {
try {
const parts = line.split(',');
const event = parts[1].substring(parts[1].indexOf('(') + 1, parts[1].lastIndexOf(')'));
const key = parts[2].substring(parts[2].indexOf('(') + 1, parts[2].indexOf(')'));
const type = parseInt(parts[3].split(' ').pop());
return { event: event, key: key, type: type };
} catch (err) {
return;
}
}
shouldBeDelayed(event) {
if (event.delay === undefined || event.delay === 0 || event.captured === undefined) {
return false;
}
return new Date().getTime() - event.captured < event.delay;
}
isStartOfCombo(key, event, parsedEvent) {
if (event.combo === undefined || this.currentCombo !== undefined) {
2022-03-03 03:35:34 +01:00
return false;
}
let possibilities = [];
for (let [actionKey, actionEvent] of this.actions) {
if (actionEvent.combo === undefined || actionEvent.combo.length === 0) {
continue;
}
if (!actionKey.toUpperCase().startsWith(parsedEvent.key)) {
continue;
}
possibilities.push(actionEvent.combo);
}
2022-03-03 03:35:34 +01:00
this.currentCombo = {
key: key,
type: event.type,
2022-03-03 03:52:34 +01:00
delay: event.delay,
timestamp: new Date().getTime(),
done: [parsedEvent.key],
possibilities: [event.combo]
2022-03-03 03:35:34 +01:00
};
return true;
}
isPartOfCombo(parsedEvent) {
if (this.hasComboTimedOut()) {
this.resetCurrentCombo();
}
if (this.currentCombo === undefined) {
return false;
}
if (this.currentCombo.done.includes(parsedEvent.key)) {
parsedEvent.ignore = true;
return true;
}
if (this.currentCombo.type.id !== parsedEvent.type) {
2022-02-15 04:33:19 +01:00
return false;
}
let combos = [];
for (let index = 0; index < this.currentCombo.possibilities.length; index++) {
const possibility = this.currentCombo.possibilities[index];
if (possibility[0].toUpperCase() !== parsedEvent.key) {
continue;
}
combos.push(possibility);
}
if (combos.length === 0) {
2022-03-03 03:35:34 +01:00
return false;
}
this.currentCombo.key = parsedEvent.key;
2022-03-03 03:52:34 +01:00
this.currentCombo.timestamp = new Date().getTime();
2022-03-03 03:35:34 +01:00
this.currentCombo.done.push(parsedEvent.key);
if (this.currentCombo.possibilities.length === 1) {
this.currentCombo.finished = true;
}
2022-03-03 03:35:34 +01:00
return true;
}
hasComboTimedOut() {
return false;
2022-03-03 03:52:34 +01:00
const result = this.currentCombo !== undefined &&
2022-03-03 03:35:34 +01:00
this.currentCombo.delay !== undefined &&
2022-03-03 03:52:34 +01:00
this.currentCombo.timestamp !== undefined &&
new Date().getTime() - this.currentCombo.timestamp > this.currentCombo.delay;
return result;
2022-03-03 03:35:34 +01:00
}
resetCurrentCombo() {
this.currentCombo = undefined;
2022-02-15 04:33:19 +01:00
}
isValid() {
return this.actions != undefined && this.actions.size > 0;
}
2022-03-10 14:05:08 +01:00
2022-02-15 04:33:19 +01:00
}
2022-03-10 14:05:08 +01:00
function getCommand(command) {
if (command === undefined || config.commands === undefined) {
return;
}
const result = config.commands[command];
if (result === undefined) {
return;
}
result.name = command;
return result;
}
2022-03-03 03:35:34 +01:00
2022-02-15 04:33:19 +01:00
module.exports = Keyfilter;