Browse Source

Adding help message support

pull/10/head
Drew Short 5 years ago
parent
commit
eb2f2a006b
  1. 68
      bot/engine.js
  2. 6
      bot/module/abstract.js
  3. 37
      bot/module/help.js
  4. 21
      bot/utility.js
  5. 5
      package-lock.json
  6. 1
      package.json

68
bot/engine.js

@ -1,11 +1,41 @@
let { logger } = require('./logging'); let { logger } = require('./logging');
let { modules } = require('./module/index')
let { modules } = require('./module/index');
let trie = require('trie-prefix-tree');
let { getShortestPrefix } = require('./utility');
let help = require('./module/help');
let message = require('./message');
let utility = require('./utility');
let sentinelValue = '!';
class Engine { class Engine {
constructor(config, bot, modules) { constructor(config, bot, modules) {
this.config = config
this.config = config;
this.bot = bot; this.bot = bot;
this.modules = modules; this.modules = modules;
this.moduleMap = new Map();
this.commandMap = new Map();
this.commandRadixTree = trie([]);
}
initModules() {
this.modules.forEach((module) => {
logger.info("Loading module: %s", module.name);
this.moduleMap.set(module.command, module);
this.commandMap.set(module.command, module);
this.commandRadixTree.addWord(module.command);
});
this.modules.forEach((module) => {
let shortCommand = getShortestPrefix(this.commandRadixTree, module.command, 3);
logger.info("Adding short command %s for module: %s", shortCommand, module.name);
this.commandMap.set(shortCommand, module);
});
this.helpModule = help.create(this.moduleMap)
this.commandMap.set('help', this.helpModule);
logger.info("Bound modules to keywords: %o", this.moduleMap);
} }
init() { init() {
@ -13,12 +43,36 @@ class Engine {
this.initModules(); this.initModules();
/* Bind Message Parsing */ /* Bind Message Parsing */
let engine = this;
let handleMessages = (event, room, toStartOfTimeline) => { let handleMessages = (event, room, toStartOfTimeline) => {
/* Don't process messages from self */
if (event.sender.userId !== this.config.userId) {
/* don't process messages that aren't of type m.room.message */
if (event.getType() !== "m.room.message") { if (event.getType() !== "m.room.message") {
logger.debug("Recieved message of type: %s", event.getType()); logger.debug("Recieved message of type: %s", event.getType());
return; // only use messages
return;
} else {
let messageBody = event.event.content.body;
logger.debug("[%s] %s", room.name, messageBody);
if (messageBody.indexOf(sentinelValue) === 0) {
let command = messageBody.split(' ')[0].substring(1);
var responseMessage = null;
if (engine.commandMap.has(command)) {
responseMessage = engine.commandMap.get(command).handleMessage(event, room);
} else { } else {
logger.debug("[%s] %s", room.name, event.event.content.body);
responseMessage = engine.helpModule.help();
}
logger.debug("Responding to room: %s", room.roomId);
if (responseMessage instanceof Object) {
engine.bot.client.sendMessage(room.roomId, responseMessage);
} else if (utility.isString(responseMessage)) {
engine.bot.client.sendMessage(room.roomId, message.createBasic(responseMessage));
} else {
logger.error("Unable to process response message: %s", responseMessage);
}
}
}
} }
} }
@ -44,12 +98,6 @@ class Engine {
return this; return this;
} }
initModules() {
this.modules.forEach((module) => {
logger.info("Loading module: %s", module.name);
});
}
run() { run() {
this.bot.connect(); this.bot.connect();
return this; return this;

6
bot/module/abstract.js

@ -3,6 +3,7 @@
*/ */
let { logger } = require('../logging'); let { logger } = require('../logging');
let message = require('../message');
class AbstractModule { class AbstractModule {
name = "AbstractModule" name = "AbstractModule"
@ -17,6 +18,11 @@ class AbstractModule {
handleMessage(event, room) { handleMessage(event, room) {
logger.debug("[%s] [%s] [%s]", this.name, room.name, event.event.content.body); logger.debug("[%s] [%s] [%s]", this.name, room.name, event.event.content.body);
return message.createBasic(this.name + " processed the message");
}
help(event, room) {
return message.createBasic(this.name + " HELP!");
} }
} }

37
bot/module/help.js

@ -0,0 +1,37 @@
/**
* Help module
*/
let { AbstractModule } = require('./abstract');
let { logger } = require('../logging');
class HelpModule extends AbstractModule {
constructor(commandMap) {
super(
"Help",
"Provide helpful information about other modules.",
"help"
);
this.commandMap = commandMap;
}
addCommand(command, module) {
logger.debug("Adding help for command %s against module %s", command, module.name);
this.commands.push(command);
}
help() {
let help = `!help <command>`;
for (let command of Array.from(this.commandMap.keys()).sort()) {
help += "\n!help " + command + " : " + this.commandMap.get(command).description;
}
return help;
}
}
function create(commandMap) {
return new HelpModule(commandMap);
}
exports.create = create;
exports.module = new HelpModule();

21
bot/utility.js

@ -1,6 +1,21 @@
let fs = require('fs'); let fs = require('fs');
let { logger } = require('./logging'); let { logger } = require('./logging');
function getShortestPrefix(radixTree, key, sliceSize) {
let shortKey = key.substring(0, sliceSize);
let keyCount = radixTree.countPrefix(shortKey);
if (keyCount < 1) {
return null;
}
if (key.length === sliceSize && radixTree.getPrefix(shortKey).includes(key)) {
return null;
}
if (keyCount === 1) {
return shortKey;
}
return getShortestPrefix(radixTree, key, sliceSize + 1);
}
function toISODateString(d) { function toISODateString(d) {
function pad(n) { return n < 10 ? '0' + n : n } function pad(n) { return n < 10 ? '0' + n : n }
return d.getUTCFullYear() + '-' return d.getUTCFullYear() + '-'
@ -29,6 +44,12 @@ function sleep(ms) {
}) })
} }
function isString(s) {
return typeof(s) === 'string' || s instanceof String;
}
exports.getShortestPrefix = getShortestPrefix;
exports.toISODateString = toISODateString; exports.toISODateString = toISODateString;
exports.getBuildInfo = getBuildInfo; exports.getBuildInfo = getBuildInfo;
exports.sleep = sleep; exports.sleep = sleep;
exports.isString = isString;

5
package-lock.json

@ -1177,6 +1177,11 @@
} }
} }
}, },
"trie-prefix-tree": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/trie-prefix-tree/-/trie-prefix-tree-1.5.1.tgz",
"integrity": "sha512-Jjvj/dA97wXnabG/NLJUgo4IQMj6vucH+Qxm7of/omfWSmZlPqdRU6Ta4GmQqCZH+n3/iYZUwfvUoEhB0Hs83Q=="
},
"triple-beam": { "triple-beam": {
"version": "1.3.0", "version": "1.3.0",
"resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.3.0.tgz", "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.3.0.tgz",

1
package.json

@ -9,6 +9,7 @@
}, },
"dependencies": { "dependencies": {
"matrix-js-sdk": "2.4.5", "matrix-js-sdk": "2.4.5",
"trie-prefix-tree": "^1.5.1",
"winston": "^3.2.1" "winston": "^3.2.1"
}, },
"devDependencies": { "devDependencies": {

Loading…
Cancel
Save