slapp
Version:
A module for Slack App integrations
119 lines (98 loc) • 3.05 kB
JavaScript
const EventEmitter = require('events')
const fs = require('fs')
const Message = require('../message')
const ParseEvent = require('./middleware/parse-event')
const ParseCommand = require('./middleware/parse-command')
const ParseAction = require('./middleware/parse-action')
const ParseOptions = require('./middleware/parse-options')
const VerifyToken = require('./middleware/verify-token')
const CheckSignature = require('./middleware/check-signature')
const SSLCheck = require('./middleware/ssl-check')
/**
* Receives HTTP requests with Events, Slash Commands, and Actions
* @private
*/
module.exports = class Receiver extends EventEmitter {
constructor (opts) {
super()
opts = opts || {}
this.verify_token = opts.verify_token
this.signing_secret = opts.signing_secret
this.signing_version = opts.signing_version
this.context = opts.context
// record all events to a JSON line delimited file if record is set
if (opts.record) {
this.started = Date.now()
fs.writeFileSync(opts.record, '')
this.on('message', (obj) => {
fs.appendFile(opts.record, JSON.stringify(Object.assign({}, obj, { delay: Date.now() - this.started })) + '\n')
})
}
}
/**
* Attach receiver HTTP route to an express app
*/
attachToExpress (app, opts) {
let defaults = {
event: '/slack/event',
command: '/slack/command',
action: '/slack/action',
options: '/slack/options'
}
let options = opts || defaults
// replace any `true` values w/ default paths
Object.keys(options).forEach((type) => {
options[type] = options[type] === true ? defaults[type] : options[type]
})
let defaultMiddlware = [
SSLCheck(),
VerifyToken(this.verify_token, this.emit.bind(this, 'error')),
CheckSignature(this.signing_secret, this.signing_version, this.emit.bind(this, 'error')),
this.context,
this.emitHandler.bind(this)
]
if (options.event) {
app.post(options.event,
ParseEvent(),
...defaultMiddlware
)
}
if (options.command) {
app.post(options.command,
ParseCommand(),
...defaultMiddlware
)
}
if (options.action) {
app.post(options.action,
ParseAction(),
...defaultMiddlware
)
}
if (options.options) {
app.post(options.options,
ParseOptions(),
...defaultMiddlware
)
}
return app
}
emitHandler (req, res) {
let message = req.slapp
if (!message) {
return res.send('Missing req.slapp')
}
let msg = new Message(message.type, message.body, message.meta)
if (message.response && message.responseTimeout) {
// Attaching the response will delegate responsibility of closing it
this.attachResponse(msg, message.response, message.responseTimeout)
} else {
res.send()
}
this.emit('message', msg)
}
attachResponse (msg, response, timeout) {
msg.attachResponse(response, timeout)
}
}