slack-command-router/index.js

116 lines
3.1 KiB
JavaScript

var _ = require('lodash'),
Formidable = require('formidable'),
EventEmitter = require('events').EventEmitter;
function Slacker() {
}
_.assign(Slacker.prototype, EventEmitter.prototype);
function SlashCommand(body, res) {
//Things from the server
this.token = body.token;
this.teamId = body.team_id;
this.channelId = body.channel_id;
this.channelName = body.channel_name;
this.userId = body.user_id;
this.userName = body.user_name;
this.command = body.command;
this.text = body.text;
this.res = res;
//State variables
this._hasReplied = false;
}
_.assign(SlashCommand.prototype, {
_generalReply: function() {
if (this.hasReplied) {
throw {
message: "Only one handler can respond to a command"
}
}
this.hasReplied = true;
},
replyUser: function (message) {
this._generalReply();
this.res.end(message);
},
tryReplyUser: function(message) {
if (this.hasReplied)
return false;
this.replyUser(message);
return true;
},
/* TODO
replyChannel: function () {
this._generalReply();
this.res.end();
},*/
error: function (message) {
this._generalReply();
this.res.writeHead(400);
this.res.end(message);
},
tryError: function (message) {
if (this.hasReplied)
return false;
this.error(message);
return true;
}
});
function SlackIncoming(commands) {
this.router = new Slacker();
if (typeof commands === "object") {
for (var handlerName in commands) {
if (commands.hasOwnProperty(handlerName)) {
this.registerHandler(commands[handlerName]);
}
}
}
}
(function () {
var checkedFields = ["token", "team_id", "channel_id", "channel_name", "user_id", "user_name", "command", "text"];
function checkCommand(fields) {
return _.xor(_.keys(fields), checkedFields).length === 0;
}
_.assign(SlackIncoming.prototype, {
registerHandler: function (handler) {
handler(this.router);
},
getMiddleware: function () {
var self = this;
return function (req, res, next) {
var form = new Formidable.IncomingForm();
form.encoding = 'utf-8';
form.type = 'urlencoded';
form.maxFieldsSize = 8192;
form.maxFields = 15;
form.parse(req, function (err, fields, files) {
if (err || !checkCommand(fields)
//Actually run the handlers
|| !self.router.emit(fields.command.slice(1), new SlashCommand(fields, res))) {
//This will only happen if there were no handlers for our event
next();
}
});
form.on('error', function(){
next();
});
form.on('aborted', function(){
next();
});
}
}
});
})();
module.exports = SlackIncoming;