function BotFrameworkBot(configuration) {
// Create a core botkit bot
var bf_botkit = Botkit(configuration || {});
// customize the bot definition, which will be used when new connections
// spawn!
bf_botkit.defineBot(function(botkit, config) {
var bot = {
botkit: botkit,
config: config || {},
utterances: botkit.utterances,
};
bot.startConversation = function(message, cb) {
botkit.startConversation(this, message, cb);
};
bot.send = function(message, cb) {
function done(err) {
if (cb) {
cb(err);
}
}
if (!message || !message.address) {
if (cb) {
cb(new Error('Outgoing message requires a valid address...'));
}
return;
}
// Copy message minus user & channel fields
var bf_message = {};
for (var key in message) {
switch (key) {
case 'user':
case 'channel':
// ignore
break;
default:
bf_message[key] = message[key];
break;
}
}
if (!bf_message.type) {
bf_message.type = 'message';
}
// Ensure the message address has a valid conversation id.
if (!bf_message.address.conversation) {
bot.connector.startConversation(bf_message.address, function(err, adr) {
if (!err) {
// Send message through connector
bf_message.address = adr;
bot.connector.send([bf_message], done);
} else {
done(err);
}
});
} else {
// Send message through connector
bot.connector.send([bf_message], done);
}
};
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;
msg.address = src.address;
bot.say(msg, cb);
};
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();
};
// Create connector
bot.connector = new builder.ChatConnector(config);
return bot;
});
// set up a web route for receiving outgoing webhooks and/or slash commands
bf_botkit.createWebhookEndpoints = function(webserver, bot, cb) {
// Listen for incoming events
bf_botkit.log(
'** Serving webhook endpoints for the Microsoft Bot Framework at: ' +
'http://' + bf_botkit.config.hostname + ':' +
bf_botkit.config.port + '/botframework/receive');
webserver.post('/botframework/receive', bot.connector.listen());
// Receive events from chat connector
bot.connector.onEvent(function(events, done) {
for (var i = 0; i < events.length; i++) {
// Break out user & chann ......
To connect your bot to the Bot Framework follow the step by step guide outlined in [Getting Started](#getting-started).
Here is the complete code for a basic Bot Framework bot:
```javascript
var Botkit = require('botkit');
var controller = Botkit.botframeworkbot({
});
var bot = controller.spawn({
appId: process.env.app_id,
appPassword: process.env.app_password
});
...function TextBot(configuration) {
// Create a core botkit bot
var text_botkit = Botkit(configuration || {});
text_botkit.middleware.spawn.use(function(bot, next) {
text_botkit.listenStdIn(bot);
next();
});
text_botkit.defineBot(function(botkit, config) {
var bot = {
botkit: botkit,
config: config || {},
utterances: botkit.utterances,
};
bot.startConversation = function(message, cb) {
botkit.startConversation(this, message, cb);
};
bot.send = function(message, cb) {
console.log('BOT:', message.text);
};
bot.reply = function(src, resp, cb) {
var msg = {};
if (typeof(resp) == 'string') {
msg.text = resp;
} else {
msg = resp;
}
msg.channel = src.channel;
bot.say(msg, cb);
};
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.debug('FOUND EXISTING CONVO!');
cb(botkit.tasks[t].convos[c]);
return;
}
}
}
cb();
};
return bot;
});
text_botkit.listenStdIn = function(bot) {
text_botkit.startTicking();
var rl = readline.createInterface({ input: process.stdin, output: process.stdout, terminal: false });
rl.on('line', function(line) {
var message = {
text: line,
user: 'user',
channel: 'text',
timestamp: Date.now()
};
text_botkit.receiveMessage(bot, message);
});
};
return text_botkit;
}...
-> http://howdy.ai/botkit
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
var Botkit = require('./lib/Botkit.js');
var os = require('os');
var controller = Botkit.consolebot({
debug: false,
});
var bot = controller.spawn();
controller.hears(['hello', 'hi'], 'message_received', function(bot, message) {
...function Botkit(configuration) {
var botkit = {
events: {}, // this will hold event handlers
config: {}, // this will hold the configuration
tasks: [],
taskCount: 0,
convoCount: 0,
my_version: null,
my_user_agent: null,
memory_store: {
users: {},
channels: {},
teams: {},
}
};
botkit.utterances = {
yes: new RegExp(/^(yes|yea|yup|yep|ya|sure|ok|y|yeah|yah)/i),
no: new RegExp(/^(no|nah|nope|n)/i),
quit: new RegExp(/^(quit|cancel|end|stop|done|exit|nevermind|never mind)/i)
};
// define some middleware points where custom functions
// can plug into key points of botkits process
botkit.middleware = {
send: ware(),
receive: ware(),
spawn: ware(),
heard: ware(),
capture: ware(),
};
function Conversation(task, message) {
this.messages = [];
this.sent = [];
this.transcript = [];
this.context = {
user: message.user,
channel: message.channel,
bot: task.bot,
};
this.events = {};
this.vars = {};
this.threads = {};
this.thread = null;
this.status = 'new';
this.task = task;
this.source_message = message;
this.handler = null;
this.responses = {};
this.capture_options = {};
this.startTime = new Date();
this.lastActive = new Date();
this.collectResponse = function(key, value) {
this.responses[key] = value;
};
this.capture = function(response, cb) {
var that = this;
var capture_key = this.sent[this.sent.length - 1].text;
botkit.middleware.capture.run(that.task.bot, response, that, function(err, bot, response, convo) {
if (response.text) {
response.text = response.text.trim();
} else {
response.text = '';
}
if (that.capture_options.key != undefined) {
capture_key = that.capture_options.key;
}
// capture the question that was asked
// if text is an array, get 1st
if (typeof(that.sent[that.sent.length - 1].text) == 'string') {
response.question = that.sent[that.sent.length - 1].text;
} else if (Array.isArray(that.sent[that.sent.length - 1].text)) {
response.question = that.sent[that.sent.length - 1].text[0];
} else {
response.question = '';
}
if (that.capture_options.multiple) {
if (!that.responses[capture_key]) {
that.responses[capture_key] = [];
}
that.responses[capture_key].push(response);
} else {
that.responses[capture_key] = response;
}
if (cb) cb(response);
});
};
this.handle = function(message) {
that = this;
this.lastActive = new Date();
this.transcript.push(message);
botkit.debug('HANDLING MESSAGE IN CONVO', message);
// do other stuff like call custom callbacks
if (this.handler) {
this.capture(message, function(message) {
// if the handler is a normal function, just execute it!
// NOTE: anyone who passes in their own handler has to call
// convo.next() to continue after completing whatever it is they want to do.
if (typeof(that.handler) == 'function') {
that.handler(message, that);
} else {
// handle might be a mapping of keyword to callback.
// lets see if the message matches any of the keywords
var match, p ...n/a
function Facebookbot(configuration) {
var api_host = configuration.api_host || 'graph.facebook.com';
// Create a core botkit bot
var facebook_botkit = Botkit(configuration || {});
if (facebook_botkit.config.require_delivery) {
facebook_botkit.on('message_delivered', function(bot, message) {
// get list of mids in this message
for (var m = 0; m < message.delivery.mids.length; m++) {
var mid = message.delivery.mids[m];
// loop through all active conversations this bot is having
// and mark messages in conversations as delivered = true
bot.findConversation(message, function(convo) {
if (convo) {
for (var s = 0; s < convo.sent.length; s++) {
if (convo.sent[s].sent_timestamp <= message.delivery.watermark ||
(convo.sent[s].api_response && convo.sent[s].api_response.mid == mid)) {
convo.sent[s].delivered = true;
}
}
}
});
}
});
}
// customize the bot definition, which will be used when new connections
// spawn!
facebook_botkit.defineBot(function(botkit, config) {
var bot = {
type: 'fb',
botkit: botkit,
config: config || {},
utterances: botkit.utterances,
};
bot.startConversation = function(message, cb) {
botkit.startConversation(this, message, cb);
};
bot.createConversation = function(message, cb) {
botkit.createConversation(this, message, cb);
};
bot.send = function(message, cb) {
var facebook_message = {
recipient: {},
message: message.sender_action ? undefined : {}
};
if (typeof(message.channel) == 'string' && message.channel.match(/\+\d+\(\d\d\d\)\d\d\d\-\d\d\d\d/)) {
facebook_message.recipient.phone_number = message.channel;
} else {
facebook_message.recipient.id = message.channel;
}
if (!message.sender_action) {
if (message.text) {
facebook_message.message.text = message.text;
}
if (message.attachment) {
facebook_message.message.attachment = message.attachment;
}
if (message.sticker_id) {
facebook_message.message.sticker_id = message.sticker_id;
}
if (message.quick_replies) {
// sanitize the length of the title to maximum of 20 chars
var titleLimit = function(title) {
if (title.length > 20) {
var newTitle = title.substring(0, 16) + '...';
return newTitle;
} else {
return title;
}
};
facebook_message.message.quick_replies = message.quick_replies.map(function(item) {
var quick_reply = {};
if (item.content_type === 'text' || !item.content_type) {
quick_reply = {
content_type: 'text',
title: titleLimit(item.title),
payload: item.payload,
image_url: item.image_url,
};
} else if (item.content_type === 'location') {
quick_reply = {
content_type: 'location'
};
} else {
// Future quick replies types
}
return quick_reply;
}); ......
To connect your bot to Facebook, [follow the instructions here](https://developers.facebook.com/docs/messenger-platform/implementation
). You will need to collect your `page token` as well as a `verify token` that you define yourself and configure inside Facebook
's app settings. A step by step guide [can be found here](#getting-started). Since you must *already be running* your Botkit
app to configure your Facebook app, there is a bit of back-and-forth. It's ok! You can do it.
Here is the complete code for a basic Facebook bot:
```javascript
var Botkit = require('botkit');
var controller = Botkit.facebookbot({
access_token: process.env.access_token,
verify_token: process.env.verify_token,
})
var bot = controller.spawn({
});
...function Slackbot(configuration) {
// Create a core botkit bot
var slack_botkit = Botkit(configuration || {});
// Set some default configurations unless they've already been set.
// Should the RTM connections ingest received messages
// Developers using the new Events API will set this to false
// This allows an RTM connection to be kept alive (so bot appears online)
// but receive messages only via events api
if (slack_botkit.config.rtm_receive_messages === undefined) {
slack_botkit.config.rtm_receive_messages = true;
}
var spawned_bots = [];
// customize the bot definition, which will be used when new connections
// spawn!
slack_botkit.defineBot(require(__dirname + '/Slackbot_worker.js'));
// Middleware to track spawned bots and connect existing RTM bots to incoming webhooks
slack_botkit.middleware.spawn.use(function(worker, next) {
// lets first check and make sure we don't already have a bot
// for this team! If we already have an RTM connection, copy it
// into the new bot so it can be used for replies.
var existing_bot = null;
if (worker.config.id) {
for (var b = 0; b < spawned_bots.length; b++) {
if (spawned_bots[b].config.id) {
if (spawned_bots[b].config.id == worker.config.id) {
// WAIT! We already have a bot spawned here.
// so instead of using the new one, use the exist one.
existing_bot = spawned_bots[b];
}
}
}
}
if (!existing_bot && worker.config.id) {
spawned_bots.push(worker);
} else if (existing_bot) {
if (existing_bot.rtm) {
worker.rtm = existing_bot.rtm;
}
}
next();
});
// set up configuration for oauth
// slack_app_config should contain
// { clientId, clientSecret, scopes}
// https://api.slack.com/docs/oauth-scopes
slack_botkit.configureSlackApp = function(slack_app_config, cb) {
slack_botkit.log('** Configuring app as a Slack App!');
if (!slack_app_config || !slack_app_config.clientId ||
!slack_app_config.clientSecret || !slack_app_config.scopes) {
throw new Error('Missing oauth config details');
} else {
slack_botkit.config.clientId = slack_app_config.clientId;
slack_botkit.config.clientSecret = slack_app_config.clientSecret;
if (slack_app_config.redirectUri) slack_botkit.config.redirectUri = slack_app_config.redirectUri;
if (typeof(slack_app_config.scopes) == 'string') {
slack_botkit.config.scopes = slack_app_config.scopes.split(/\,/);
} else {
slack_botkit.config.scopes = slack_app_config.scopes;
}
if (cb) cb(null);
}
return slack_botkit;
};
// set up a web route that is a landing page
slack_botkit.createHomepageEndpoint = function(webserver) {
slack_botkit.log('** Serving app landing page at : http://' +
slack_botkit.config.hostname + ':' + slack_botkit.config.port + '/');
// FIX THIS!!!
// this is obvs not right.
webserver.get('/', function(req, res) {
res.send('Howdy!');
});
return slack_botkit;
};
// adds the webhook authentication middleware module to the webserver
function secureWebhookEndpoints() {
var authenticationMiddleware = require(__dirname + '/middleware/slack_authentication.js');
// convert a variable argument list to an array, drop the webserver argument
var tokens = Array.prototype.slice.call(arguments);
var webserver = tokens.shift();
slack_botkit.log(
'** Requiring token authentication for webhook endpoints for Slash commands ' +
'and outgoing webhooks; configured ' + tokens.length + ' token(s)'
);
webserver.use(authent ......
Then pass the returned storage when creating your Botkit controller. Botkit will do the rest.
Make sure everything you store has an `id` property, that's what you'll use to look it up later.
```javascript
var Botkit = require('botkit'),
mongoStorage = require('botkit-storage-mongo')({mongoUri: '...'}),
controller = Botkit.slackbot({
storage: mongoStorage
});
```
```javascript
// then you can use the Botkit storage api, make sure you have an id property
var beans = {id: 'cool', beans: ['pinto', 'garbanzo']};
...function Sparkbot(configuration) {
// Create a core botkit bot
var controller = Botkit(configuration || {});
if (!controller.config.ciscospark_access_token) {
throw new Error('ciscospark_access_token required to create controller');
} else {
controller.api = require('ciscospark').init({
credentials: {
authorization: {
access_token: controller.config.ciscospark_access_token
}
}
});
if (!controller.api) {
throw new Error('Could not create Cisco Spark API');
}
controller.api.people.get('me').then(function(identity) {
console.log('Cisco Spark: My identity is', identity);
controller.identity = identity;
}).catch(function(err) {
throw new Error(err);
});
}
if (!controller.config.public_address) {
throw new Error('public_address parameter required to receive webhooks');
} else {
var endpoint = url.parse(controller.config.public_address);
if (!endpoint.hostname) {
throw new Error('Could not determine hostname of public address: ' + controller.config.public_address);
} else if (endpoint.protocol != 'https:') {
throw new Error('Please specify an SSL-enabled url for your public address: ' + controller.config.public_address);
} else {
controller.config.public_address = endpoint.hostname + (endpoint.port ? ':' + endpoint.port : '');
}
}
if (!controller.config.secret) {
console.log('WARNING: No secret specified. Source of incoming webhooks will not be validated. https://developer.ciscospark
.com/webhooks-explained.html#auth');
// throw new Error('secret parameter required to secure webhooks');
}
controller.resetWebhookSubscriptions = function() {
controller.api.webhooks.list().then(function(list) {
for (var i = 0; i < list.items.length; i++) {
controller.api.webhooks.remove(list.items[i]).then(function(res) {
console.log('Removed subscription: ' + list.items[i].name);
}).catch(function(err) {
console.log('Error removing subscription:', err);
});
}
});
};
// set up a web route for receiving outgoing webhooks and/or slash commands
controller.createWebhookEndpoints = function(webserver, bot, cb) {
var webhook_name = controller.config.webhook_name || 'Botkit Firehose';
controller.log(
'** Serving webhook endpoints for Cisco Spark Platform at: ' +
'http://' + controller.config.hostname + ':' + controller.config.port + '/ciscospark/receive');
webserver.post('/ciscospark/receive', function(req, res) {
controller.handleWebhookPayload(req, res, bot);
});
var list = controller.api.webhooks.list().then(function(list) {
var hook_id = null;
for (var i = 0; i < list.items.length; i++) {
if (list.items[i].name == webhook_name) {
hook_id = list.items[i].id;
}
}
var hook_url = 'https://' + controller.config.public_address + '/ciscospark/receive';
console.log('Cisco Spark: incoming webhook url is ', hook_url);
if (hook_id) {
controller.api.webhooks.update({
id: hook_id,
resource: 'all',
targetUrl: hook_url,
event: 'all',
secret: controller.config.secret,
name: webhook_name,
}).then(function(res) {
console.log('Cisco Spark: SUCCESSFULLY UPDATED CISCO SPARK WEBHOOKS');
if (cb) cb();
}).catch(function(err) {
console.log('FAILED TO REGISTER WEBHOOK', err);
throw new Error(err);
});
} else { ......
This will configure your bot to respond only to messages from members of the specific organization, or whose email addresses match
one of the specified domains.
The full code for a simple Cisco Spark bot is below:
```
var Botkit = require('./lib/Botkit.js');
var controller = Botkit.sparkbot({
debug: true,
log: true,
public_address: process.env.public_address,
ciscospark_access_token: process.env.access_token,
secret: process.env.secret
});
...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.startConversation = function(message, cb) {
botkit.startConversation(this, message, cb);
};
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 se ......
To connect your bot to Twilio, [follow the instructions here](https://www.twilio.com/user/account/ip-messaging/getting-started).
You will need to collect 5 separate pieces of your API credentials. A step by step guide [can be found here](#getting-started).
Since you must *already be running* your Botkit app to fully configure your Twilio app, there is a bit of back-and-forth. It'
;s ok! You can do it.
Here is the complete code for a basic Twilio bot:
```javascript
var Botkit = require('botkit');
var controller = Botkit.twilioipmbot({
debug: false
})
var bot = controller.spawn({
TWILIO_IPM_SERVICE_SID: process.env.TWILIO_IPM_SERVICE_SID,
TWILIO_ACCOUNT_SID: process.env.TWILIO_ACCOUNT_SID,
TWILIO_API_KEY: process.env.TWILIO_API_KEY,
...