UNPKG

mangrove-botkit

Version:

Building blocks for Building Bots

369 lines (299 loc) 13.7 kB
var Botkit = require(__dirname + '/CoreBot.js'); var request = require('request'); var twilio = require('twilio'); var async = require('async'); var AccessToken = twilio.AccessToken; var IpMessagingGrant = AccessToken.IpMessagingGrant; function Twiliobot(configuration) { // Create a core botkit bot var twilio_botkit = Botkit(configuration || {}); // customize the bot definition, which will be used when new connections // spawn! twilio_botkit.defineBot(function(botkit, config) { var bot = { type: 'twilioipm', botkit: botkit, config: config || {}, utterances: botkit.utterances, }; bot.send = function(message, cb) { botkit.debug('SEND ', message); if (bot.identity === null || bot.identity === '') { bot.api.channels(message.channel).messages.create({ body: message.text, }).then(function(response) { cb(null, response); }).catch(function(err) { cb(err); }); } else { bot.api.channels(message.channel).messages.create({ body: message.text, from: bot.identity }).then(function(response) { cb(null, response); }).catch(function(err) { cb(err); }); } }; bot.reply = function(src, resp, cb) { var msg = {}; if (typeof(resp) == 'string') { msg.text = resp; } else { msg = resp; } msg.user = src.user; msg.channel = src.channel; bot.say(msg, cb); }; bot.autoJoinChannels = function() { bot.api.channels.list().then(function(full_channel_list) { if (bot.config.autojoin === true) { bot.channels = full_channel_list; bot.channels.channels.forEach(function(chan) { bot.api.channels(chan.sid).members.create({ identity: bot.identity }).then(function(response) { botkit.debug('added ' + bot.identity + ' as a member of the ' + chan.friendly_name); }).fail(function(error) { botkit.debug('Couldn\'t join the channel: ' + chan.friendly_name + ': ' + error); }); }); } else if (bot.identity) { // load up a list of all the channels that the bot is currently bot.channels = { channels: [] }; async.each(full_channel_list.channels, function(chan, next) { bot.api.channels(chan.sid).members.list().then(function(members) { for (var x = 0; x < members.members.length; x++) { if (members.members[x].identity == bot.identity) { bot.channels.channels.push(chan); } } next(); }).fail(function(error) { botkit.log('Error loading channel member list: ', error); next(); }); }); } }).fail(function(error) { botkit.log('Error loading channel list: ' + error); // fails if no channels exist // set the channels to empty bot.channels = { channels: [] }; }); }; bot.configureBotIdentity = function() { if (bot.identity !== null || bot.identity !== '') { var userRespIter = 0; var existingIdentity = null; // try the get by identity thing bot.api.users(bot.identity).get().then(function(response) { bot.autoJoinChannels(); }).fail(function(error) { // if not make the new user and see if they need to be added to all the channels bot.api.users.create({ identity: bot.identity }).then(function(response) { bot.autoJoinChannels(); }).fail(function(error) { botkit.log('Could not get Bot Identity:'); botkit.log(error); process.exit(1); }); }); } }; /** * This handles the particulars of finding an existing conversation or * topic to fit the message into... */ bot.findConversation = function(message, cb) { botkit.debug('CUSTOM FIND CONVO', message.user, message.channel); for (var t = 0; t < botkit.tasks.length; t++) { for (var c = 0; c < botkit.tasks[t].convos.length; c++) { if ( botkit.tasks[t].convos[c].isActive() && botkit.tasks[t].convos[c].source_message.user == message.user && botkit.tasks[t].convos[c].source_message.channel == message.channel ) { botkit.debug('FOUND EXISTING CONVO!'); cb(botkit.tasks[t].convos[c]); return; } } } cb(); }; bot.client = new twilio.IpMessagingClient(config.TWILIO_ACCOUNT_SID, config.TWILIO_AUTH_TOKEN); bot.api = bot.client.services(config.TWILIO_IPM_SERVICE_SID); if (config.identity) { bot.identity = config.identity; bot.configureBotIdentity(); } return bot; }); // set up a web route for receiving outgoing webhooks and/or slash commands twilio_botkit.createWebhookEndpoints = function(webserver, bot) { twilio_botkit.log( '** Serving webhook endpoints for receiving messages ' + 'webhooks at: http://' + twilio_botkit.config.hostname + ':' + twilio_botkit.config.port + '/twilio/receive'); webserver.post('/twilio/receive', function(req, res) { res.status(200); res.send('ok'); twilio_botkit.handleWebhookPayload(req, res, bot); }); return twilio_botkit; }; twilio_botkit.handleWebhookPayload = function(req, res, bot) { // ensure all messages // have a user & channel var message = req.body; if (req.body.EventType == 'onMessageSent') { // customize fields to be compatible with Botkit message.text = req.body.Body; message.from = req.body.From; message.to = req.body.To; message.user = req.body.From; message.channel = req.body.ChannelSid; twilio_botkit.receiveMessage(bot, message); }else if (req.body.EventType == 'onChannelAdded' || req.body.EventType == 'onChannelAdd') { // this event has a channel sid but not a user message.channel = req.body.ChannelSid; twilio_botkit.trigger(req.body.EventType, [bot, message]); }else if (req.body.EventType == 'onChannelDestroyed' || req.body.EventType == 'onChannelDestroy') { // this event has a channel sid but not a user message.channel = req.body.ChannelSid; twilio_botkit.trigger(req.body.EventType, [bot, message]); }else if (req.body.EventType == 'onMemberAdded' || req.body.EventType == 'onMemberAdd') { // should user be MemberSid the The Member Sid of the newly added Member message.user = req.body.Identity; message.channel = req.body.ChannelSid; twilio_botkit.trigger(req.body.EventType, [bot, message]); } else if (req.body.EventType == 'onMemberRemoved' || req.body.EventType == 'onMemberRemove') { message.user = req.body.Identity; message.channel = req.body.ChannelSid; twilio_botkit.trigger(req.body.EventType, [bot, message]); if (req.body.EventType == 'onMemberRemoved') { } } else { twilio_botkit.trigger(req.body.EventType, [bot, message]); } }; // handle events here twilio_botkit.handleTwilioEvents = function() { twilio_botkit.log('** Setting up custom handlers for processing Twilio messages'); twilio_botkit.on('message_received', function(bot, message) { if (bot.identity && message.from == bot.identity) { return false; } if (!message.text) { // message without text is probably an edit return false; } if (bot.identity) { var channels = bot.channels.channels; // if its not in a channel with the bot var apprChan = channels.filter(function(ch) { return ch.sid == message.channel; }); if (apprChan.length === 0) { return false; } } }); // if a member is removed from a channel, check to see if it matches the bot's identity // and if so remove it from the list of channels the bot listens to twilio_botkit.on('onMemberRemoved', function(bot, message) { if (bot.identity && message.user == bot.identity) { // remove that channel from bot.channels.channels var chan_to_rem = bot.channels.channels.map(function(ch) { return ch.sid; }).indexOf(message.channel); if (chan_to_rem != -1) { bot.channels.channels.splice(chan_to_rem, 1); twilio_botkit.debug('Unsubscribing from channel because of memberremove.'); } } else if (bot.identity) { var channels = bot.channels.channels; // if its not in a channel with the bot var apprChan = channels.filter(function(ch) { return ch.sid == message.channel; }); if (apprChan.length === 0) { return false; } } if (bot.identity && bot.identity == message.user) { twilio_botkit.trigger('bot_channel_leave', [bot, message]); } else { twilio_botkit.trigger('user_channel_leave', [bot, message]); } }); twilio_botkit.on('onMemberAdded', function(bot, message) { if (bot.identity && message.user == bot.identity) { bot.api.channels(message.channel).get().then(function(response) { bot.channels.channels.push(response); twilio_botkit.debug('Subscribing to channel because of memberadd.'); }).fail(function(error) { botkit.log(error); }); } else if (bot.identity) { var channels = bot.channels.channels; // if its not in a channel with the bot var apprChan = channels.filter(function(ch) { return ch.sid == message.channel; }); if (apprChan.length === 0) { return false; } } if (bot.identity && bot.identity == message.user) { twilio_botkit.trigger('bot_channel_join', [bot, message]); } else { twilio_botkit.trigger('user_channel_join', [bot, message]); } }); // if a channel is destroyed, remove it from the list of channels this bot listens to twilio_botkit.on('onChannelDestroyed', function(bot, message) { if (bot.identity) { var chan_to_rem = bot.channels.channels.map(function(ch) { return ch.sid; }).indexOf(message.channel); if (chan_to_rem != -1) { bot.channels.channels.splice(chan_to_rem, 1); twilio_botkit.debug('Unsubscribing from destroyed channel.'); } } }); // if a channel is created, and the bot is set in autojoin mode, join the channel twilio_botkit.on('onChannelAdded', function(bot, message) { if (bot.identity && bot.config.autojoin === true) { // join the channel bot.api.channels(message.channel).members.create({ identity: bot.identity }).then(function(response) { bot.api.channels(message.channel).get().then(function(response) { bot.channels.channels.push(response); twilio_botkit.debug('Subscribing to new channel.'); }).fail(function(error) { botkit.log(error); }); }).fail(function(error) { botkit.log(error); }); } }); }; twilio_botkit.startTicking(); twilio_botkit.handleTwilioEvents(); return twilio_botkit; } module.exports = Twiliobot;