Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Burner slackbot integration #1

Merged
merged 9 commits into from
Mar 19, 2016
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
FROM node:5.3.0

MAINTAINER xVir <danil.skachkov@speaktoit.com>
MAINTAINER Matt Buck <matt@voxable.io>

RUN mkdir -p /usr/app/src
WORKDIR /usr/app
Expand Down
133 changes: 22 additions & 111 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,125 +1,36 @@
# Api.ai Slack Integration
# Intelligent SMS bot via Burner, Slack, and Api.ai

## Overview

Api.ai Slack integration allows you to create Slack bots with natural language understanding based on Api.ai technology.
By making use of [Burner's Slack connection](http://www.burnerapp.com/slack/) and [Api.ai's Slack integration](https://docs.api.ai/docs/slack-integration), you can easily create an intelligent SMS bot.

[![Deploy to Heroku](https://www.herokucdn.com/deploy/button.svg)](https://heroku.com/deploy)

To launch a bot, you’ll need the Linux OS. To launch it in other operating systems, use [Docker Toolbox](https://www.docker.com/products/docker-toolbox).
![burner api-ai slackbot mp4](https://cloud.githubusercontent.com/assets/2220/13895572/a82a92ba-ed42-11e5-8960-8dc91471d64a.gif)

Api.ai documentation:
What's happening above:

- [How to create an Api.ai agent](https://docs.api.ai/docs/get-started#step-1-create-agent)
- [How to obtain Api.ai authentication keys](https://docs.api.ai/docs/authentication)
* A user sends a text to our Burner line.
* The Burner Slack connection posts the SMS in our Slack channel.
* Our slackbot receives the SMS, parses out the sending phone number and message, and passes these on to our Api.ai agent.
* Our Api.ai agent sends back a response, which our slackbot duly posts in the Slack channel, prepended with the number that sent the SMS.
* The Burner Slack connection sends an SMS back to the user.

You’ll need 3 keys:
## Getting Started

- Client access token for Api.ai
- Subscription key for Api.ai
- Slack bot API token
1. [Create an Api.ai agent.](https://docs.api.ai/docs/get-started#step-1-create-agent)
2. [Activate the general knowledge domain for your agent.](https://docs.api.ai/docs/domains)
3. [Obtain your Api.ai authentication keys.](https://docs.api.ai/docs/authentication)
4. [Create a new slackbot.](https://slack.com/apps/A0F7YS25R-bots)
5. [Obtain your Slackbot's API token.](https:/lslack.com/apps/manage/A0F7YS25R-bots)
6. [Enable the Slack connection for your Burner line.](http://www.burnerapp.com/slack/)
7. Click the handy "Deploy to Heroku" button below to deploy the bot to Heroku.

To obtain a Slack bot API token, create a new bot integration here: https://slack.com/apps/A0F7YS25R-bots.
[![Deploy to Heroku](https://www.herokucdn.com/deploy/button.svg)](https://heroku.com/deploy)

## Bot Launch
8. Enter the credentials you gathered above in the "New App" screen and click the "Create App" button.

To launch the bot, use one of the following commands:
You're all set! Try texting a question to your Burner line, and you should get a response.

**For background launch mode (-d parameter):**
## Credits

```sh
docker run -d --name slack_bot \
-e accesstoken="api.ai access key" \
-e subscriptionkey="api.ai subscription key" \
-e slackkey="slack bot key" \
api-ai/api-ai-slack-bot
```

**For interactive launch mode (-it parameter):**

```sh
docker run -it --name slack_bot \
-e accesstoken="Api.ai client access key" \
-e subscriptionkey="Api.ai subscription key" \
-e slackkey="Slack bot user key" \
api-ai/api-ai-slack-bot
```

To stop the bot from running in the interactive mode, press CTRL+C.

In the background mode, you can control the bot’s state via simple commands:


- `docker start slack_bot`
- `docker stop slack_bot`,

where `slack_bot` is the container name from the `run` command.

## Custom Bot Launch

If you want to customize your bot behavior, follow the steps below.

1. Clone the repository /~https://github.com/xVir/api-ai-slack-bot

2. Change the code to `index.js`

3. In the Docker, use the `run` command specifying the full path to the directory containing the `index.js` file:

```sh
docker run -d --name slack_bot \
-e accesstoken="Api.ai client token" \
-e subscriptionkey="Api.ai Subscription key" \
-e slackkey="Slack bot user key" \
-v /full/path/to/your/src:/usr/app/src \
api-ai/api-ai-slack-bot
```

## Code Notes

Bot implementation is based on the Slack Botkit: /~https://github.com/howdyai/botkit.

Message processing is done by the following code:

```javascript
controller.hears(['.*'],['direct_message','direct_mention','mention', 'ambient'], function(bot,message) {
console.log(message.text);
if (message.type == "message") {
if (message.user == bot.identity.id) {
// message from bot can be skipped
}
else {
var requestText = message.text;
var channel = message.channel;
if (!(channel in sessionIds)) {
sessionIds[channel] = uuid.v1();
}
var request = apiAiService.textRequest(requestText, { sessionId: sessionIds[channel] });
request.on('response', function (response) {
console.log(response);
if (response.result) {
var responseText = response.result.fulfillment.speech;
if (responseText) {
bot.reply(message, responseText);
}
}
});
request.on('error', function (error) {
console.log(error);
});
request.end();
}
}
});
```

This code extracts the text from each message:

`var requestText = message.text;`

And sends it to Api.ai:

`var request = apiAiService.textRequest(requestText, { sessionId: sessionIds[channel] });`

If a non-empty response is received from Api.ai, the bot will respond with the received text:

`bot.reply(message, responseText);`
This is a fork of [Api.ai's Slack integration](/~https://github.com/api-ai/api-ai-slack-bot), with [minimal modifications](/~https://github.com/voxable-labs/burner-sms-api-ai-slackbot/pull/1/files#diff-1fdf421c05c1140f6d71444ea2b27638) needed to make the magic happen with Burner.
10 changes: 5 additions & 5 deletions app.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
{
"name": "API.AI with Slack integration",
"description": "Api.ai Slack integration allows you to create Slack bots with natural language understanding based on Api.ai technology.",
"repository": "/~https://github.com/api-ai/api-ai-slack-bot",
"logo": "https://console.api.ai/api-client/assets/img/logo-black.png",
"keywords": ["api.ai", "slack", "natural language"],
"name": "Burner to Api.ai slackbot",
"description": "A slackbot that enables connecting Burner lines to the Api.ai platform via Burner's Slack connection.",
"repository": "/~https://github.com/voxable-labs/burner-sms-api-ai-slackbot",
"logo": "https://avatars1.githubusercontent.com/u/15236552?v=3&s=200",
"keywords": ["api.ai", "slack", "natural language", "slackbot", "burner", "voxable"],
"env": {
"accesstoken": {
"description": "Client access token for Api.ai",
Expand Down
23 changes: 20 additions & 3 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ function isDefined(obj) {
return obj != null;
}

controller.hears(['.*'], ['direct_message', 'direct_mention', 'mention', 'ambient'], function (bot, message) {
controller.hears(['.*'], ['bot_message'], function (bot, message) {

try {
if (message.type == 'message') {
Expand All @@ -56,16 +56,32 @@ controller.hears(['.*'], ['direct_message', 'direct_mention', 'mention', 'ambien
else if (message.text.indexOf("<@U") == 0 && message.text.indexOf(bot.identity.id) == -1) {
// skip other users direct mentions
}
else if (message.text.includes("Sent text to")) {
// skip sent text confirmations from Burner
console.log('Skipping Burner response.');
}
else {

var requestText = decoder.decode(message.text);
requestText = requestText.replace("’", "'");

var burnerMesageRegex = /Inbound message from \+(\d*):\s(.*)/;
var returnNumber = '';
var smsMessage;

// Parse the SMS message and return number out of Burner's slackbot message
if ((smsMessage = burnerMesageRegex.exec(requestText)) !== null) {
returnNumber = '@' + smsMessage[1];
requestText = smsMessage[2];

console.log('returnNumber', returnNumber);
console.log('requestText', requestText);
}

var channel = message.channel;
var messageType = message.event;
var botId = "<@" + bot.identity.id + ">";

console.log(requestText);
console.log(messageType);

if (requestText.indexOf(botId) > -1) {
Expand All @@ -85,7 +101,8 @@ controller.hears(['.*'], ['direct_message', 'direct_mention', 'mention', 'ambien
console.log(response);

if (isDefined(response.result)) {
var responseText = response.result.fulfillment.speech;
// Preface the response with the appropriate return SMS number.
var responseText = returnNumber + ' ' + response.result.fulfillment.speech;
var action = response.result.action;

if (isDefined(responseText)) {
Expand Down