├── .gitignore
├── CONTRIBUTING.md
├── docs
├── app_structure.md
├── bot_instance.md
├── controller.md
├── conversations.md
├── core.md
├── examples.md
├── functions.md
├── glitch.png
├── hosting-your-own-bot.md
├── howto
│ ├── build_connector.md
│ ├── build_middleware.md
│ └── upgrade_05to06.md
├── index.md
├── logging.md
├── middleware.md
├── provisioning
│ ├── IMG
│ │ ├── Slack-eventsenable.png
│ │ ├── botkit_icon.png
│ │ ├── cisco_add.png
│ │ ├── fb_app_perm.png
│ │ ├── fb_mess.png
│ │ ├── fb_new.png
│ │ ├── fb_tokengen.png
│ │ ├── fb_webhooks.png
│ │ ├── fb_webhooks_com.png
│ │ ├── slack-botuser.png
│ │ ├── slack-im.png
│ │ ├── slack-new.png
│ │ ├── slack_botevents.png
│ │ ├── slack_client_secret.png
│ │ └── slack_oauth.png
│ ├── cisco-spark.md
│ ├── facebook_messenger.md
│ ├── index.md
│ ├── slack-events-api.md
│ ├── teams.md
│ └── twilio-sms.md
├── readme-botframework.md
├── readme-ciscojabber.md
├── readme-ciscospark.md
├── readme-facebook.md
├── readme-google-hangouts.md
├── readme-middlewares.md
├── readme-pipeline.md
├── readme-slack.md
├── readme-studio.md
├── readme-teams.md
├── readme-twilioipm.md
├── readme-twiliosms.md
├── readme-web.md
├── readme-webex.md
├── slack-events-api.md
├── starterkits.md
├── storage.md
├── studio.png
├── studio_script_author2.png
├── toc.md
└── what_is_a_bot.md
├── readme.md
└── todo.md
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | */.DS_Store
3 | .idea/
4 | .vscode
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Instructions for Contributing Code
2 |
3 | This project welcomes contributions and suggestions. Most contributions require you to agree to a
4 | Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us
5 | the rights to use your contribution. For details, visit https://cla.microsoft.com.
6 |
7 | When you submit a pull request, a CLA-bot will automatically determine whether you need to provide
8 | a CLA and decorate the PR appropriately (e.g., label, comment). Simply follow the instructions
9 | provided by the bot. You will only need to do this once across all repos using our CLA.
10 |
11 | ## Code of Conduct
12 |
13 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
14 |
--------------------------------------------------------------------------------
/docs/app_structure.md:
--------------------------------------------------------------------------------
1 | # Botkit App Structure
2 |
3 |
4 | bot.js
5 | skills/
6 |
--------------------------------------------------------------------------------
/docs/bot_instance.md:
--------------------------------------------------------------------------------
1 | # Botkit Bot Instances
2 |
3 |
4 | #### bot.say()
5 | | Argument | Description
6 | |--- |---
7 | | message | A message object
8 | | callback | _Optional_ Callback in the form function(err,response) { ... }
9 |
10 | Slack-specific Example:
11 | ```javascript
12 | bot.say(
13 | {
14 | text: 'my message text',
15 | channel: 'C0H338YH4' // a valid slack channel, group, mpim, or im ID
16 | }
17 | );
18 | ```
19 | Note: If your primary need is to spontaneously send messages rather than respond to incoming messages, you may want to use [Slack's incoming webhooks feature](readme-slack.md#incoming-webhooks) rather than the real time API.
20 |
21 |
22 | Facebook-specific Example:
23 | ```javascript
24 | bot.say(
25 | {
26 | text: 'my message_text',
27 | channel: '+1(###)###-####' // a valid facebook user id or phone number
28 | }
29 | );
30 | ```
31 |
32 | #### bot.reply()
33 | | Argument | Description
34 | |--- |---
35 | | message | Incoming message object
36 | | reply | _String_ or _Object_ Outgoing response
37 | | callback | _Optional_ Callback in the form function(err,response) { ... }
38 |
39 | Simple reply example:
40 | ```javascript
41 | controller.hears(['keyword','^pattern$'],['message_received'],function(bot,message) {
42 |
43 | // do something to respond to message
44 | // ...
45 |
46 | bot.reply(message,"Tell me more!");
47 |
48 | });
49 | ```
50 |
51 |
52 |
53 | #### bot.startConversation()
54 | | Argument | Description
55 | |--- |---
56 | | message | incoming message to which the conversation is in response
57 | | callback | a callback function in the form of function(err,conversation) { ... }
58 |
59 | `startConversation()` is a function that creates conversation in response to an incoming message.
60 | The conversation will occur _in the same channel_ in which the incoming message was received.
61 | Only the user who sent the original incoming message will be able to respond to messages in the conversation.
62 |
63 | #### bot.startPrivateConversation()
64 | | Argument | Description
65 | |--- |---
66 | | message | message object containing {user: userId} of the user you would like to start a conversation with
67 | | callback | a callback function in the form of function(err,conversation) { ... }
68 |
69 | `startPrivateConversation()` is a function that initiates a conversation with a specific user. Note function is currently *Slack-only!*
70 |
71 | #### bot.createConversation()
72 | | Argument | Description
73 | |--- |---
74 | | message | incoming message to which the conversation is in response
75 | | callback | a callback function in the form of function(err,conversation) { ... }
76 |
77 | This works just like `startConversation()`, with one main difference - the conversation
78 | object passed into the callback will be in a dormant state. No messages will be sent,
79 | and the conversation will not collect responses until it is activated using [convo.activate()](#conversationactivate).
80 |
81 | Use `createConversation()` instead of `startConversation()` when you plan on creating more complex conversation structures using [threads](#conversation-threads) or [variables and templates](#using-variable-tokens-and-templates-in-conversation-threads) in your messages.
82 |
83 | #### bot.createPrivateConversation()
84 | | Argument | Description
85 | |--- |---
86 | | message | incoming message to which the conversation is in response
87 | | callback | a callback function in the form of function(err,conversation) { ... }
88 |
89 | This works just like `startPrivateConversation()`, with one main difference - the conversation
90 | object passed into the callback will be in a dormant state. No messages will be sent,
91 | and the conversation will not collect responses until it is activated using [convo.activate()](#conversationactivate).
92 |
--------------------------------------------------------------------------------
/docs/controller.md:
--------------------------------------------------------------------------------
1 | # Botkit Controller Object
2 |
3 | #### controller.hears()
4 | | Argument | Description
5 | |--- |---
6 | | patterns | An _array_ or a _comma separated string_ containing a list of regular expressions to match
7 | | types | An _array_ or a _comma separated string_ of the message events in which to look for the patterns
8 | | middleware function | _optional_ function to redefine how patterns are matched. see [Botkit Middleware](middleware.md)
9 | | callback | callback function that receives a message object
10 |
11 | Example:
12 | ```javascript
13 | controller.hears(['keyword','^pattern$'],['message_received'],function(bot,message) {
14 |
15 | // do something to respond to message
16 | bot.reply(message,'You used a keyword!');
17 |
18 | });
19 | ```
20 |
21 | When using the built in regular expression matching, the results of the expression will be stored in the `message.match` field and will match the expected output of normal Javascript `string.match(/pattern/i)`.
22 |
23 | For example:
24 |
25 | ```javascript
26 | controller.hears('open the (.*) doors',['message_received'],function(bot,message) {
27 | var doorType = message.match[1]; //match[1] is the (.*) group. match[0] is the entire group (open the (.*) doors).
28 | if (doorType === 'pod bay') {
29 | return bot.reply(message, 'I\'m sorry, Dave. I\'m afraid I can\'t do that.');
30 | }
31 | return bot.reply(message, 'Okay');
32 | });
33 | ```
34 |
35 |
36 | #### controller.on()
37 | | Argument | Description
38 | |--- |---
39 | | event_name | a string or array containing an event or comma-separated list of events
40 | | callback | callback function in the form of form of function(bot, event) {...}
41 |
42 | Handle events emitted by Botkit. The vast majority of events will call a callback function with 2 parameters - a bot instance, and the event object.
43 |
44 | [Read about receiving and handling events](core.md#responding-to-events)
45 |
46 | ```javascript
47 | // handle a message event
48 | controller.on('message_received', function(bot, message) {
49 | bot.reply(message,'Received');
50 | });
51 |
52 | // handle a channel join event
53 | controller.on('channel_join', function(bot, event) {
54 | bot.reply(event,'Welcome to the channel!');
55 | });
56 | ```
57 |
58 | Note that you may also trigger your own events using [controller.trigger()](#controllertrigger) and handle them. This can be
59 | useful for separating the trigger logic from the actual event handlers, as in the example below.
60 |
61 | ```javascript
62 |
63 | // listen for a help request.. and then trigger a help_request event.
64 | controller.hears('help', 'message_received', function(bot, message) {
65 | // this event can be triggered whenever a user needs help
66 | bot.trigger('help_request', [bot, message]);
67 | });
68 |
69 | controller.on('help_request', function(bot, message) {
70 |
71 | bot.reply(message,'I am here to help!');
72 |
73 | });
74 | ```
75 |
76 | #### controller.trigger()
77 | | Argument | Description
78 | |--- |---
79 | | event_name | the name of a custom event
80 | | parameters | an array of parameters to be passed on to any handler functions
81 |
82 | Triggers a custom event, which can then be handled by [controller.on()](#controlleron).
83 |
84 | The second argument to `controller.trigger()` is an array which should contain an array of parameters that will be passed on to any handler functions. While not required, it is highly recommended that custom events conform to the pattern used by native Botkit events and include a bot instance as the first parameter, and if applicable, a normalized Botkit event object as the second paramter:
85 |
86 | ```javascript
87 | controller.trigger('my_custom_event', [bot, event]);
88 | ```
89 |
90 | #### controller.changeEars()
91 | | Argument | Description
92 | |--- |---
93 | | test_function | a function in the form function(tests_array, message_object)
94 |
95 | This function can be used to modify the way Botkit's hearing system works by replacing the pattern matching function with a custom function.
96 |
97 | The test function must perform synchronous tests, and should return true if the message represents a match, and otherwise return false.
98 |
99 | Code based on Botkit's built-in regular expression test is below:
100 |
101 | ```
102 | var hears_regexp = function(tests, message) {
103 | for (var t = 0; t < tests.length; t++) {
104 | if (message.text) {
105 |
106 | // the pattern might be a string to match (including regular expression syntax)
107 | // or it might be a prebuilt regular expression
108 | var test = null;
109 | if (typeof(tests[t]) == 'string') {
110 | try {
111 | test = new RegExp(tests[t], 'i');
112 | } catch (err) {
113 | botkit.log('Error in regular expression: ' + tests[t] + ': ' + err);
114 | return false;
115 | }
116 | if (!test) {
117 | return false;
118 | }
119 | } else {
120 | test = tests[t];
121 | }
122 |
123 | if (match = message.text.match(test)) {
124 | message.match = match;
125 | return true;
126 | }
127 | }
128 | }
129 | return false;
130 | };
131 |
132 | controller.changeEars(hears_regexp);
133 | ```
134 |
135 | #### controller.excludeFromConversations()
136 |
137 | | Argument | Description
138 | |--- |---
139 | | events | single event or an array of events to exclude from conversations
140 |
141 | Messaging platforms send a dizzying array of event types - and new ones are added all the time!
142 |
143 | Sometimes, it is desirable to exclude certain event types from inclusion in Botkit conversations. To do this, call `excludeFromConversations()` after creating your controller object.
144 |
145 | For example:
146 |
147 | ```javascript
148 | // always exclude facebook postback events from conversations
149 | controller.excludeFromConversations('facebook_postback')
150 | ```
151 |
152 | #### controller.spawn()
153 | | Argument | Description
154 | |--- |---
155 | | configuration | an object with instance-specific configuration options
156 | | callback | a function that will receive the new bot instance as a parameter
157 |
158 | Spawn a new instance of the bot in order to send messages or handle replies.
159 |
160 | Whenever the bot is doing something in response to an incoming message, Botkit will handle spawning bot instances for you. However, in the event that your bot needs to send an alert or subscription message that is not directly in reply to an incoming message, spawning a bot is required.
161 |
162 | The configuration options required to spawn a bot instance differ from platform to platform. In many cases, no additional configuration is required. Refer to the platform specific documnentation for more detail.
163 |
164 | ```javascript
165 | function sendAlertToBot(alert_message) {
166 |
167 | controller.spawn({}, function(bot) {
168 |
169 | bot.say(alert_message);
170 |
171 | });
172 |
173 | }
174 | ```
175 |
176 | #### controller.defineBot()
177 | | Argument | Description
178 | |--- |---
179 | | bot_constructor | function of the form function(botkit_controller, configuration) which returns a bot instance
180 |
181 | This function is used to create new platform connectors for Botkit, and is used to define the specific behaviors and features of that platform's bot instance.
182 |
183 | For more information, [read the guide to creating new platform connectors for Botkit](howto/build_connector.md)
184 |
185 |
186 | #### controller.setTickDelay()
187 | | Argument | Description
188 | |--- |---
189 | | delay | time between event loops
190 |
191 | Adjust the speed of Botkit's event loops. By default, this is set to 1500ms, which means that Botkit will evaluate all active conversations and send any pending replies every 1.5 seconds.
192 |
193 | Decreasing this time will increase the speed at which bots send replies in conversations.
194 |
195 | For example:
196 | ``` javascript
197 | // only wait 100ms between conversation loops
198 | controller.setTickDelay(100);
199 | ```
200 |
201 | #### controller.startTicking()
202 |
203 | This function begins Botkit's internal event loop, which will tick at an interval of once every 1.5 seconds unless modified using [controller.setTickDelay()](#controller-settickdelay)
204 |
205 | In most cases, this is called internally by a platform connector and does not have to be called directly by bot code.
206 |
207 | However, if your bot seems to freeze up after the first message in any conversation, you may need to call it!
208 |
209 |
210 | #### controller.setupWebserver(port, cb)
211 | | Argument | Description
212 | |--- |---
213 | | port | a port number for the webserver
214 | | callback | a function in the form function(err, webserver) {...}
215 |
216 | Create an instance of the [Express.js webserver](https://expressjs.com) for use with platform-specific features like oauth and incoming webhooks.
217 |
218 | Botkit provides a simple Express webserver for those who don't know or don't want to set up their own. However, if you want to do anything with your webserver other than those required by Botkit, it is our recommendation that you manage your own instance of Express. A good place to see this in action is [inside all of the botkit starter kits](starterkits.md).
219 |
220 | #### controller.userAgent()
221 |
222 | Returns a user agent string for use when making API requests to external resources.
223 |
224 | #### controller.version()
225 |
226 | Returns the current package version of Botkit's core library
227 |
228 | #### controller.shutdown()
229 |
230 | This function _stops_ the event loop from processing active conversations. It is the opposite of [controller.startTicking()](#controller-startticking)
231 |
--------------------------------------------------------------------------------
/docs/conversations.md:
--------------------------------------------------------------------------------
1 | # Botkit Conversation Objects
2 |
3 |
4 | #### convo.activate()
5 |
6 | This function will cause a dormant conversation created with [bot.createConversation()](#botcreateconversation) to be activated, which will cause it to start sending messages and receiving replies from end users.
7 |
8 | A conversation can be kept dormant in order to preload it with [variables](#using-variable-tokens-and-templates-in-conversation-threads), particularly data that requires asynchronous actions to take place such as loading data from a database or remote source. You may also keep a conversation inactive while you build threads, setting it in motion only when all of the user paths have been defined.
9 |
10 | #### convo.addMessage
11 | | Argument | Description
12 | |--- |---
13 | | message | String or message object
14 | | thread_name | String defining the name of a thread
15 |
16 | This function works identically to `convo.say()` except that it takes a second parameter which defines the thread to which the message will be added rather than being queued to send immediately, as is the case when using convo.say().
17 |
18 | #### convo.addQuestion
19 | | Argument | Description
20 | |--- |---
21 | | message | String or message object containing the question
22 | | callback _or_ array of callbacks | callback function in the form function(response_message,conversation), or array of objects in the form ``{ pattern: regular_expression, callback: function(response_message,conversation) { ... } }``
23 | | capture_options | Object defining options for capturing the response. Pass an empty object if capture options are not needed
24 | | thread_name | String defining the name of a thread
25 |
26 |
27 | When passed a callback function, conversation.ask will execute the callback function for any response.
28 | This allows the bot to respond to open ended questions, collect the responses, and handle them in whatever
29 | manner it needs to.
30 |
31 | When passed an array, the bot will look first for a matching pattern, and execute only the callback whose
32 | pattern is matched. This allows the bot to present multiple choice options, or to proceed
33 | only when a valid response has been received. At least one of the patterns in the array must be marked as the default option,
34 | which will be called should no other option match. Botkit comes pre-built with several useful patterns which can be used with this function. See [included utterances](#included-utterances)
35 |
36 | Callback functions passed to `addQuestion()` receive two parameters - the first is a standard message object containing
37 | the user's response to the question. The second is a reference to the conversation itself.
38 |
39 | Note that in order to continue the conversation, `convo.next()` must be called by the callback function. This
40 | function tells Botkit to continue processing the conversation. If it is not called, the conversation will hang
41 | and never complete causing memory leaks and instability of your bot application!
42 |
43 | The optional third parameter `capture_options` can be used to define different behaviors for collecting the user's response.
44 | This object can contain the following fields:
45 |
46 | | Field | Description
47 | |--- |---
48 | | key | _String_ If set, the response will be stored and can be referenced using this key
49 | | multiple | _Boolean_ if true, support multi-line responses from the user (allow the user to respond several times and aggregate the response into a single multi-line value)
50 |
51 | ##### Using conversation.addQuestion with a callback:
52 |
53 | ```javascript
54 | controller.hears(['question me'], 'message_received', function(bot,message) {
55 |
56 | // start a conversation to handle this response.
57 | bot.startConversation(message,function(err,convo) {
58 |
59 | convo.addQuestion('How are you?',function(response,convo) {
60 |
61 | convo.say('Cool, you said: ' + response.text);
62 | convo.next();
63 |
64 | },{},'default');
65 |
66 | })
67 |
68 | });
69 | ```
70 |
71 | ##### Using conversation.addQuestion with an array of callbacks:
72 |
73 | ```javascript
74 | controller.hears(['question me'], 'message_received', function(bot,message) {
75 |
76 | // start a conversation to handle this response.
77 | bot.startConversation(message,function(err,convo) {
78 |
79 | convo.addQuestion('Shall we proceed Say YES, NO or DONE to quit.',[
80 | {
81 | pattern: 'done',
82 | callback: function(response,convo) {
83 | convo.say('OK you are done!');
84 | convo.next();
85 | }
86 | },
87 | {
88 | pattern: bot.utterances.yes,
89 | callback: function(response,convo) {
90 | convo.say('Great! I will continue...');
91 | // do something else...
92 | convo.next();
93 |
94 | }
95 | },
96 | {
97 | pattern: bot.utterances.no,
98 | callback: function(response,convo) {
99 | convo.say('Perhaps later.');
100 | // do something else...
101 | convo.next();
102 | }
103 | },
104 | {
105 | default: true,
106 | callback: function(response,convo) {
107 | // just repeat the question
108 | convo.repeat();
109 | convo.next();
110 | }
111 | }
112 | ],{},'default');
113 |
114 | })
115 |
116 | });
117 | ```
118 |
119 | #### convo.say()
120 | | Argument | Description
121 | |--- |---
122 | | message | String or message object
123 |
124 | convo.say() is a specialized version of `convo.addMessage()` that adds messages to the _current_ thread, essentially adding a message dynamically to the conversation. This should only be used in simple cases, or when building a conversation with lots of dynamic content. Otherwise, creating `threads` is the recommended approach.
125 |
126 | Call convo.say() several times in a row to queue messages inside the conversation. Only one message will be sent at a time, in the order they are queued.
127 |
128 | ```javascript
129 | controller.hears(['hello world'], 'message_received', function(bot,message) {
130 |
131 | // start a conversation to handle this response.
132 | bot.startConversation(message,function(err,convo) {
133 |
134 | convo.say('Hello!');
135 | convo.say('Have a nice day!');
136 |
137 | });
138 | });
139 | ```
140 |
141 | #### convo.ask()
142 | | Argument | Description
143 | |--- |---
144 | | message | String or message object containing the question
145 | | callback _or_ array of callbacks | callback function in the form function(response_message,conversation), or array of objects in the form ``{ pattern: regular_expression, callback: function(response_message,conversation) { ... } }``
146 | | capture_options | _Optional_ Object defining options for capturing the response
147 |
148 | convo.ask() is a specialized version of `convo.addQuestion()` that adds messages to the _current_ thread, essentially adding a message dynamically to the conversation. This should only be used in simple cases, or when building a conversation with lots of dynamic content. Otherwise, creating `threads` is the recommended approach.
149 |
150 | In particular, we recommend that developers avoid calling `convo.ask()` or `convo.say()` inside a callbacks for `convo.ask()`. Multi-level callbacks encourage fragile code - for conversations requiring more than one branch, use threads!
151 |
152 |
153 | #### convo.gotoThread()
154 | | Argument | Description
155 | |--- |---
156 | | thread_name | String defining the name of a thread
157 |
158 | Cause the bot to immediately jump to the named thread.
159 | All conversations start in a thread called `default`, but you may switch to another existing thread before the conversation has been activated, or in a question callback.
160 |
161 | Threads are created by adding messages to them using `addMessage()` and `addQuestion()`
162 |
163 | ```javascript
164 | // create the validation_error thread
165 | convo.addMessage('This is a validation error.', 'validation_error');
166 | convo.addMessage('I am sorry, your data is wrong!', 'validation_error');
167 |
168 | // switch to the validation thread immediately
169 | convo.gotoThread('validation_error');
170 | ```
171 |
172 |
173 | #### convo.transitionTo
174 | | Argument | Description
175 | |--- |---
176 | | thread_name | String defining the name of a thread
177 | | message | String or message object
178 |
179 | Like `gotoThread()`, jumps to the named thread. However, before doing so,
180 | Botkit will first send `message` to the user as a transition. This allows
181 | developers to specify dynamic transition messages to improve the flow of the
182 | conversation.
183 |
184 | ```javascript
185 | // create an end state thread
186 | convo.addMessage('This is the end!', 'the_end');
187 |
188 | // now transition there with a nice message
189 | convo.transitionTo('the_end','Well I think I am all done.');
190 | ```
191 |
192 | #### convo.beforeThread
193 | | Argument | Description
194 | |--- |---
195 | | thread_name | String defining the name of a thread
196 | | handler_function | handler in the form function(convo, next) {...}
197 |
198 | Allows developers to specify one or more functions that will be called before the thread
199 | referenced in `thread_name` is activated.
200 |
201 | `handler_function` will receive the conversation object and a `next()` function. Developers
202 | must call the `next()` function when their asynchronous operations are completed, or the conversation
203 | may not continue as expected.
204 |
205 | Note that if `gotoThread()` is called inside the handler function,
206 | it is recommended that `next()` be passed with an error parameter to stop processing of any additional thread handler functions that may be defined - that is, call `next('stop');`
207 |
208 | ```javascript
209 | // create a thread that asks the user for their name.
210 | // after collecting name, call gotoThread('completed') to display completion message
211 | convo.addMessage({text: 'Hello let me ask you a question, then i will do something useful'},'default');
212 | convo.addQuestion({text: 'What is your name?'},function(res, convo) {
213 | // name has been collected...
214 | convo.gotoThread('completed');
215 | },{key: 'name'},'default');
216 |
217 | // create completed thread
218 | convo.addMessage({text: 'I saved your name in the database, {{vars.name}}'},'completed');
219 |
220 | // create an error thread
221 | convo.addMessage({text: 'Oh no I had an error! {{vars.error}}'},'error');
222 |
223 |
224 | // now, define a function that will be called AFTER the `default` thread ends and BEFORE the `completed` thread begins
225 | convo.beforeThread('completed', function(convo, next) {
226 |
227 | var name = convo.extractResponse('name');
228 |
229 | // do something complex here
230 | myFakeFunction(name).then(function(results) {
231 |
232 | convo.setVar('results',results);
233 |
234 | // call next to continue to the secondary thread...
235 | next();
236 |
237 | }).catch(function(err) {
238 | convo.setVar('error', err);
239 | convo.gotoThread('error');
240 | next(err); // pass an error because we changed threads again during this transition
241 | });
242 |
243 | });
244 | ```
245 |
246 |
247 | #### convo.setVar
248 | | Argument | Description
249 | |--- |---
250 | | variable_name | The name of a variable to be made available to message text templates.
251 | | value | The value of the variable, which can be any type of normal Javascript variable
252 |
253 | Create or update a variable that is available as a Mustache template token to all the messages in all the threads contained in the conversation.
254 |
255 | The variable will be available in the template as `{{vars.variable_name}}`
256 |
257 | #### convo.onTimeout()
258 | | Argument | Description
259 | |--- |---
260 | | callback | _Optional_ Callback in the form function(convo) { ... }
261 |
262 | Provide a handler function that will be called in the event that a conversation reaches its timeout threshold without any user response.
263 |
264 |
265 | #### convo.extractResponses()
266 |
267 | Returns an object containing all of the responses a user sent during the course of a conversation.
268 |
269 | ```javascript
270 | var values = convo.extractResponses();
271 | var value = values.key;
272 | ```
273 |
274 | #### convo.extractResponse()
275 |
276 | Return one specific user response, identified by its key.
277 |
278 | ```javascript
279 | var value = convo.extractResponse('key');
280 | ```
281 |
282 |
283 | `convo.sayFirst(message)` Works just like convo.say, but injects a message into the first spot in the queue
284 | so that it is sent immediately, before any other queued messages.
285 |
286 | `convo.stop()` end the conversation immediately, and set convo.status to `stopped`
287 |
288 | `convo.repeat()` repeat the last question sent and continue to wait for a response.
289 |
290 | `convo.silentRepeat()` simply wait for another response without saying anything.
291 |
292 | `convo.next()` proceed to the next message in the conversation. *This must be called* at the end of each handler.
293 |
294 | `convo.setTimeout(timeout)` times out conversation if no response from user after specified time period (in milliseconds).
295 |
296 |
297 | #### convo.hasThread()
298 |
299 | #### convo.successful()
300 |
--------------------------------------------------------------------------------
/docs/examples.md:
--------------------------------------------------------------------------------
1 |
2 | ## Included Examples
3 |
4 | These examples are included in the Botkit [Github repo](https://github.com/howdyai/botkit).
5 |
6 | [slack_bot.js](https://github.com/howdyai/botkit/blob/master/examples/slack_bot.js) An example bot that can be connected to your team. Useful as a basis for creating your first bot!
7 |
8 | [spark_bot.js](https://github.com/howdyai/botkit/blob/master/examples/spark_bot.js) An example bot that can be connected to Cisco Spark. Useful as a basis for creating your first bot!
9 |
10 | [facebook_bot.js](https://github.com/howdyai/botkit/blob/master/examples/facebook_bot.js) An example bot that can be connected to your Facebook page. Useful as a basis for creating your first bot!
11 |
12 | [twilio_sms_bot.js](https://github.com/howdyai/botkit/blob/master/examples/twilio_sms_bot.js) An example bot that can be connected to your Twilio SMS service. Useful as a basis for creating your first bot!
13 |
14 | [twilio_ipm_bot.js](https://github.com/howdyai/botkit/blob/master/examples/twilio_ipm_bot.js) An example bot that can be connected to your Twilio IP Messaging client. Useful as a basis for creating your first bot!
15 |
16 | [botframework_bot.js](https://github.com/howdyai/botkit/blob/master/examples/botframework_bot.js) An example bot that can be connected to the Microsoft Bot Framework network. Useful as a basis for creating your first bot!
17 |
18 | [examples/demo_bot.js](https://github.com/howdyai/botkit/blob/master/examples/slack/demo_bot.js) another example bot that uses different ways to send and receive messages.
19 |
20 | [examples/team_outgoingwebhook.js](https://github.com/howdyai/botkit/blob/master/examples/slack/team_outgoingwebhook.js) an example of a Botkit app that receives and responds to outgoing webhooks from a single team.
21 |
22 | [examples/team_slashcommand.js](https://github.com/howdyai/botkit/blob/master/examples/slack/team_slashcommand.js) an example of a Botkit app that receives slash commands from a single team.
23 |
24 | [examples/slackbutton_bot.js](https://github.com/howdyai/botkit/blob/master/examples/slack/slackbutton_bot.js) an example of using the Slack Button to offer a bot integration.
25 |
26 | [examples/slackbutton_incomingwebhooks.js](https://github.com/howdyai/botkit/blob/master/examples/slack/slackbutton_incomingwebhooks.js) an example of using the Slack Button to offer an incoming webhook integration. This example also includes a simple form which allows you to broadcast a message to any team who adds the integration.
27 |
28 | [example/sentiment_analysis.js](https://github.com/howdyai/botkit/blob/master/examples/slack/sentiment_analysis.js) a simple example of a chatbot using sentiment analysis. Keeps a running score of each user based on positive and negative keywords. Messages and thresholds can be configured.
29 |
--------------------------------------------------------------------------------
/docs/functions.md:
--------------------------------------------------------------------------------
1 | # Botkit Controller
2 |
3 | controller.middleware.*
4 |
5 | controller.changeEars
6 |
7 | controller.hears
8 |
9 | controller.on
10 |
11 | controller.trigger
12 |
13 | controller.spawn
14 |
15 | controller.receiveMessage
16 |
17 | controller.version
18 |
19 | controller.log
20 |
21 | ... and then platform specific features too
22 |
23 |
24 |
25 | # Bot Object
26 |
27 | bot.reply
28 |
29 | bot.say
30 |
31 | bot.startConversation
32 |
33 | bot.createConversation
34 |
35 | ... and lots of specific featres added by platforms
36 |
37 |
38 |
39 |
40 | # Conversation Object
41 |
42 | convo.setVar
43 |
44 | convo.activate
45 |
46 | convo.isActive
47 |
48 | convo.deactivate
49 |
50 | convo.say
51 |
52 | convo.sayFirst
53 |
54 | convo.on
55 |
56 | convo.trigger
57 |
58 | convo.next
59 |
60 | convo.repeat
61 |
62 | convo.silentRepeat
63 |
64 | convo.addQuestion
65 |
66 | convo.ask
67 |
68 | convo.setTimeout
69 |
70 | convo.onTimeout
71 |
72 | convo.hasThread
73 |
74 | convo.transitionTo
75 |
76 | convo.gotoThread
77 |
78 | convo.getResponses
79 |
80 | convo.getResponsesAsArray
81 |
82 | convo.extractResponses
83 |
84 | convo.extractResponse
85 |
86 | convo.stop
87 |
88 | convo.successful
89 |
90 | convo.cloneMessage
91 |
--------------------------------------------------------------------------------
/docs/glitch.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/howdyai/botkit-docs/6569c40ec68762ae526cd2d4987765944f8c5cee/docs/glitch.png
--------------------------------------------------------------------------------
/docs/hosting-your-own-bot.md:
--------------------------------------------------------------------------------
1 | # How To Host Your Botkit App
2 |
3 | This is a placeholder for forthcoming docs. Sorry!
4 |
5 | ## the gist
6 |
7 | Get a server somewhere. [Digital Ocean](https://m.do.co/c/c8d2cb189d36) is a good choice, but Botkit runs in Azure, AWS, Heroku and others.
8 |
9 | Get your process up and running on some port - 3000 by default.
10 |
11 | Set up letsencrypt or some other SSL solution. Most messaging platforms now require that your endpoint be served over SSL.
12 |
13 | Set up nginx to serve your ssl-enabled website and proxy traffic to the bot application on port 3000.
14 |
15 | Voila! You have a ssl-enabled bot.
16 |
17 | ### Optional next steps:
18 | * Only accept requests over https.
19 | * Block access to port 3000
20 |
21 |
22 | ## related topics
23 |
24 | * scaling up with multiple bot processes
25 | * botkit and continuous integration
26 |
--------------------------------------------------------------------------------
/docs/howto/build_connector.md:
--------------------------------------------------------------------------------
1 | # How to build a Botkit Platform Connector
2 |
3 | Adding support to Botkit for a new platform requires building a module that gives Botkit the ability to send and receive messages ot the right APIs and in the right format.
4 |
5 | Here is an example:
6 |
7 | ```
8 | module.exports = function(Botkit, config) {
9 |
10 | var controller = Botkit.core(config);
11 |
12 | controller.defineBot(function(botkit, config) {
13 |
14 | var bot = {
15 | type: 'my_platform',
16 | botkit: botkit,
17 | config: config || {},
18 | utterances: botkit.utterances,
19 | }
20 |
21 |
22 | // here is where you make the API call to SEND a message
23 | // the message object should be in the proper format already
24 | bot.send = function(message, cb) {
25 | console.log('SEND: ', message);
26 | cb();
27 | }
28 |
29 | // this function takes an incoming message (from a user) and an outgoing message (reply from bot)
30 | // and ensures that the reply has the appropriate fields to appear as a reply
31 | bot.reply = function(src, resp, cb) {
32 | if (typeof(resp) == 'string') {
33 | resp = {
34 | text: resp
35 | }
36 | }
37 | resp.channel = src.channel;
38 | bot.say(resp, cb);
39 | }
40 |
41 | // this function defines the mechanism by which botkit looks for ongoing conversations
42 | // probably leave as is!
43 | bot.findConversation = function(message, cb) {
44 | for (var t = 0; t < botkit.tasks.length; t++) {
45 | for (var c = 0; c < botkit.tasks[t].convos.length; c++) {
46 | if (
47 | botkit.tasks[t].convos[c].isActive() &&
48 | botkit.tasks[t].convos[c].source_message.user == message.user &&
49 | botkit.excludedEvents.indexOf(message.type) == -1 // this type of message should not be included
50 | ) {
51 | cb(botkit.tasks[t].convos[c]);
52 | return;
53 | }
54 | }
55 | }
56 | cb();
57 | };
58 |
59 | return bot;
60 |
61 | })
62 |
63 |
64 | // provide one or more normalize middleware functions that take a raw incoming message
65 | // and ensure that the key botkit fields are present -- user, channel, text, and type
66 | controller.middleware.normalize.use(function(bot, message, next) {
67 |
68 | console.log('NORMALIZE', message);
69 | next();
70 |
71 | });
72 |
73 |
74 | // provide one or more ways to format outgoing messages from botkit messages into
75 | // the necessary format required by the platform API
76 | // at a minimum, copy all fields from `message` to `platform_message`
77 | controller.middleware.format.use(function(bot, message, platform_message, next) {
78 | for (var k in message) {
79 | platform_message[k] = message[k]
80 | }
81 | next();
82 | });
83 |
84 |
85 | // provide a way to receive messages - normally by handling an incoming webhook as below!
86 | controller.handleWebhookPayload = function(req, res) {
87 | var payload = req.body;
88 |
89 | var bot = controller.spawn({});
90 | controller.ingest(bot, payload, res);
91 |
92 | res.status(200);
93 | };
94 |
95 |
96 | return controller;
97 |
98 | }
99 | ```
100 |
101 | Now, load your new platform module like this:
102 |
103 | ```
104 | var controller = require('my_module')(Botkit,{});
105 | ```
106 |
--------------------------------------------------------------------------------
/docs/howto/build_middleware.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/howdyai/botkit-docs/6569c40ec68762ae526cd2d4987765944f8c5cee/docs/howto/build_middleware.md
--------------------------------------------------------------------------------
/docs/howto/upgrade_05to06.md:
--------------------------------------------------------------------------------
1 | # Upgrading Botkit 0.5 to 0.6
2 |
3 | With the introduction of the [Botkit Message Pipeline](../readme-pipeline.md),
4 | a few things changed about the way message events are
5 | emitted that may impact developers who built their
6 | bot using an earlier version of Botkit.
7 |
8 | Though we've made fairly substantial under-the-hood changes to Botkit in this version,
9 | most bots should continue to function without requiring any changes.
10 | However, as a precaution, we urge developers to carefully test their bot with the new version of Botkit before going live.
11 |
12 | ## How to upgrade Botkit
13 |
14 | Inside your Botkit application's root folder, run the command:
15 |
16 | ```
17 | npm update --save botkit
18 | ```
19 |
20 | This will cause your version of Botkit to be updated to the latest
21 | available version (0.6.0), and your package.json file will be modified.
22 |
23 | Alternately, you can edit your package.json file by hand, changing the
24 | version option for Botkit to '^0.6'.
25 |
26 | ## Does my bot require any changes?
27 |
28 | Facebook Bots that use the `receive_via_postback` option, and Slack bots that use the `interactive_replies` option may require small updates.
29 |
30 | In the past, it was sometimes possible for Botkit to emit more than one event
31 | per incoming message - in particular, when handling button click events
32 | as typed user text. This double-event behavior was enabled by configuration
33 | switches - one for Facebook, and one for Slack - which are now deprecated.
34 |
35 | As of version 0.6, incoming messages will only ever emit a single event.
36 | These button click events can will now have the button payload value included as the `message.text` property, and can thus be treated like other types of user messages.
37 |
38 | ## For Facebook Messenger Bots:
39 |
40 | The `receive_via_postback` option is no longer needed to receive button clicks as typed messages in conversations. They will now be captured automatically.
41 |
42 | In addition, developers can now include `facebook_postback` in the list
43 | of events when specifying `hears()` patterns. This will allow button clicks
44 | and other postback events to trigger heard patterns.
45 |
46 | Developers who previously used `receive_via_postback` may want to add `facebook_postback` to their hears() handlers to ensure no functionality is lost.
47 |
48 | ```
49 | controller.hears('welcome','facebook_postback', function(bot, message) {
50 | // respond when a user clicks a button with the payload value "welcome"
51 | });
52 | ```
53 |
54 | ## For Slack Bots:
55 |
56 | The `interactive_replies` is no longer needed to receive button clicks as typed messages in conversations. They will now be captured automatically.
57 |
58 | In addition, developers can now include `interactive_message_callback` in the list of events when specifying `hears()` patterns. This will allow button clicks to trigger heard patterns.
59 |
60 | Developers who previously used `interactive_replies` may want to add `interactive_message_callback` to their hears() handlers to ensure no functionality is lost.
61 |
62 | ```
63 | controller.hears('welcome','interactive_message_callback', function(bot, message) {
64 | // respond when a user clicks a button with the value set to "welcome"
65 | });
66 | ```
67 |
68 | ## Slack Starter Kit Fix
69 |
70 | In previous versions of the Slack Starter Kit, we included a clever skill which allowed buttons to be treated as typed text if the `name` of the button was set to "say." In addition to re-emitting the event as a type message, this skill also caused the message in Slack to be updated.
71 |
72 | If you use this skill and want to upgrade to the latest version of Botkit, you should replace the `skills/interactive_messages.js` file in your project with [this updated version](https://github.com/howdyai/botkit-starter-slack/blob/master/skills/interactive_messages.js).
73 |
74 | This new version now defines a `receive middleware` that looks for `interactive_message_callback` events and performs update to the message. It no longer needs to re-emit the message, as after the middleware completes, the message will pass naturally to any ongoing conversation or `hears` handler.
75 |
--------------------------------------------------------------------------------
/docs/index.md:
--------------------------------------------------------------------------------
1 | # Botkit: Building Blocks for Building Bots
2 |
3 |
4 |
5 |
6 |
7 | --------------------------------------------------------------------------------
8 |
9 | **Botkit is the leading developer tool for building chat bots, apps and custom integrations for major messaging platforms.**
10 |
11 | Botkit offers everything you need to design, build and operate an app:
12 |
13 | - Easy-to-extend starter kits
14 | - Fully-featured SDK with support for all major platforms
15 | - Content management and design tools
16 | - Analytics and CRM tools
17 | - Tons of plugins and middlewares
18 |
19 | ## Install Botkit
20 |
21 | [**New to Botkit?** Read our full guide to getting started with Botkit](/getstarted.html).
22 |
23 | ### **Remix on Glitch**
24 |
25 | Want to dive right in? [Remix one of our starter kits on Glitch](https://glitch.com/botkit). You'll start with a fully functioning app that you can edit and run from the browser!
26 |
27 | [](https://glitch.com/botkit)
28 |
29 |
30 | ### **Command Line Interface**
31 |
32 | The best way to get started locally with Botkit is by installing our command line tool, and using it to create a new Botkit project. This will install and configure a starter kit for you!
33 |
34 | ```
35 | npm install -g botkit
36 | botkit new
37 | ```
38 |
39 | ### **Start from Scratch**
40 |
41 | You can also add Botkit into an existing Node application.
42 |
43 | First, add it to your project:
44 |
45 | ```
46 | npm install --save botkit
47 | ```
48 |
49 | Then, add Botkit to your application code:
50 |
51 | ```
52 | var Botkit = require('botkit');
53 |
54 | var controller = Botkit.anywhere(configuration);
55 |
56 | controller.hears('hello','direct_message', function(bot, message) {
57 | bot.reply(message,'Hello yourself!');
58 | });
59 | ```
60 |
61 | ## Build Your Bot
62 |
63 | Botkit is programming library, along with a suite of supporting tools and plugins, that provides bot builders a platform independent, language-like interface for building a chatbot or messaging app for any platform. It handles all the nitty gritty technical details, allowing you to focus on building COOL FEATURES for your bot.
64 |
65 | The toolkit is designed to provide meaningful building blocks for creating conversational user interfaces - with functions like `hears()`, `ask()`, and `reply()` that do what they say they do.
66 |
67 | ## Hearing Messages
68 |
69 | Most bots do their thing by listening for keywords, phrases or patterns in messages from users. Botkit has a special event handler called `hears()` that makes it easy to configure your bot to listen for this type of trigger.
70 |
71 | ```javascript
72 | // listen for a message containing the world "hello", and send a reply
73 | controller.hears('hello','message_received',function(bot, message) {
74 | // do something!
75 | bot.reply(message, 'Hello human')
76 | });
77 | ```
78 |
79 | [Read more about hearing things »](core.md#matching-patterns-and-keywords-with-hears)
80 |
81 | ## Responding to Events
82 |
83 | Bots can respond to non-verbal events as well, like when a new user joins a channel, a file gets uploaded, or a button gets clicked. These events are handled using an event handling pattern that should look familiar to most developers. Most events in Botkit can be replied to like normal messages.
84 |
85 | ```javascript
86 | // wait for a new user to join a channel, then say hi
87 | controller.on('channel_join', function(bot, message) {
88 | bot.reply(message,'Welcome to the channel!');
89 | });
90 | ```
91 |
92 | [See a full list of events and more information about handling them »](core.md#receiving-messages-and-events)
93 |
94 | ## Conversation Management
95 |
96 | Botkit has a flexible system for handling scripted dialog and transactional conversations involving questions, branching logic, and other dynamic behaviors.
97 |
98 | [Read about Conversations »](core.md#multi-message-conversations)
99 |
100 |
101 | ## Extend Botkit with Middleware
102 |
103 | In addition to taking direct action in response to a certain message or type of event, Botkit can also take passive action on messages as they move through the application using middlewares. Middleware functions work by changing messages, adding new fields, firing alternate events, and modifying or overriding the behavior of Botkit's core features.
104 |
105 | Middleware can be used to adjust how Botkit receives, processes, and sends messages. [Here is a list of available middleware endpoints](middleware.md).
106 |
107 | ```javascript
108 | // Log every message received
109 | controller.middleware.receive.use(function(bot, message, next) {
110 |
111 | // log it
112 | console.log('RECEIVED: ', message);
113 |
114 | // modify the message
115 | message.logged = true;
116 |
117 | // continue processing the message
118 | next();
119 |
120 | });
121 |
122 | // Log every message sent
123 | controller.middleware.send.use(function(bot, message, next) {
124 |
125 | // log it
126 | console.log('SENT: ', message);
127 |
128 | // modify the message
129 | message.logged = true;
130 |
131 | // continue processing the message
132 | next();
133 |
134 | });
135 | ```
136 |
137 |
138 | ## What's Next?
139 |
140 | * [Continue learning about Botkit's core features](core.md)
141 | * [View set-up guides for all the major platforms](provisioning/)
142 |
--------------------------------------------------------------------------------
/docs/logging.md:
--------------------------------------------------------------------------------
1 | # Writing your own logging module
2 |
3 | By default, your bot will log to the standard JavaScript `console` object
4 | available in Node.js. This will synchronously print logging messages to stdout
5 | of the running process.
6 |
7 | There may be some cases, such as remote debugging or rotating of large logs,
8 | where you may want a more sophisticated logging solution. You can write your
9 | own logging module that uses a third-party tool, like
10 | [winston](https://github.com/winstonjs/winston) or
11 | [Bristol](https://github.com/TomFrost/Bristol). Just create an object with a
12 | `log` method. That method should take a severity level (such as `'error'` or
13 | `'debug'`) as its first argument, and then any number of other arguments that
14 | will be logged as messages. (Both Winston and Bristol create objects of this
15 | description; it's a common interface.)
16 |
17 | Then, use it when you create your bot:
18 | ```javascript
19 | var controller = Botkit.slackbot({
20 | logger: new winston.Logger({
21 | levels: winston.config.syslog.levels
22 | transports: [
23 | new (winston.transports.Console)(),
24 | new (winston.transports.File)({ filename: './bot.log' })
25 | ]
26 | })
27 | });
28 | ```
29 |
30 |
31 |
32 | Note: with Winston, we must use the syslog.levels over the default or else some botkit log messages (like 'notice') will not be logged properly.
33 |
--------------------------------------------------------------------------------
/docs/middleware.md:
--------------------------------------------------------------------------------
1 | # Middleware
2 |
3 | The functionality of Botkit can be extended using middleware
4 | functions. These functions can plugin to the core bot running processes at
5 | several useful places and make changes to both a bot's configuration and
6 | the incoming or outgoing message.
7 |
8 | For information about existing middleware plugins, [see here](readme-middlewares.md)
9 |
10 | ## Middleware Endpoints
11 |
12 | Botkit currently supports middleware insertion in the following places:
13 |
14 | * When receiving a message, before triggering any events
15 | * When sending a message, before the message is sent to the API
16 | * When hearing a message
17 | * When matching patterns with `hears()`, after the pattern has been matched but before the handler function is called
18 | * When capturing a users response to a `convo.ask()` question, after the user has answered, but before the value is stored or passed to the handler function
19 |
20 | Send and Receive middleware functions are added to Botkit using an Express-style "use" syntax.
21 | Each function receives a bot parameter, a message parameter, and
22 | a next function which must be called to continue processing the middleware stack.
23 |
24 | Hear middleware functions are passed in to the `controller.hears` function,
25 | and override the built in regular expression matching.
26 |
27 | ### Receive Middleware
28 |
29 | Receive middleware can be used to do things like preprocess the message
30 | content using external natural language processing services like Wit.ai.
31 | Additional information can be added to the message object for use down the chain.
32 |
33 | ```javascript
34 | controller.middleware.receive.use(function(bot, message, next) {
35 |
36 | // do something...
37 | // message.extrainfo = 'foo';
38 | next();
39 |
40 | });
41 | ```
42 |
43 |
44 | ### Send Middleware
45 |
46 | Send middleware can be used to do things like preprocess the message
47 | content before it gets sent out to the messaging client.
48 |
49 | ```javascript
50 | controller.middleware.send.use(function(bot, message, next) {
51 |
52 | // do something useful...
53 | if (message.intent == 'hi') {
54 | message.text = 'Hello!!!';
55 | }
56 | next();
57 |
58 | });
59 | ```
60 |
61 |
62 | ### Hear Middleware
63 |
64 | Hear middleware can be used to change the way Botkit bots "hear" triggers.
65 | It can be used to look for values in fields other than message.text, or use comparison methods other than regular expression matching. For example, a middleware function
66 | could enable Botkit to "hear" intents added by an NLP classifier instead of string patterns.
67 |
68 | Hear middleware is enabled by passing a function into the `hears()` method on the Botkit controller.
69 | When specified, the middleware function will be used instead of the built in regular expression match.
70 |
71 | These functions receive 2 parameters - `patterns` an array of patterns, and `message` the incoming
72 | message. This function will be called _after_ any receive middlewares, so may use any additional
73 | information that may have been added. A return value of `true` indicates the pattern has been
74 | matched and the bot should respond.
75 |
76 | ```javascript
77 | // this example does a simple string match instead of using regular expressions
78 | function custom_hear_middleware(patterns, message) {
79 |
80 | for (var p = 0; p < patterns.length; p++) {
81 | if (patterns[p] == message.text) {
82 | return true;
83 | }
84 | }
85 | return false;
86 | }
87 |
88 |
89 | controller.hears(['hello'],'direct_message',custom_hear_middleware,function(bot, message) {
90 |
91 | bot.reply(message, 'I heard the EXACT string match for "hello"');
92 |
93 | });
94 | ```
95 |
96 | It is possible to completely replace the built in regular expression match with
97 | a middleware function by calling `controller.changeEars()`. This will replace the matching function used in `hears()`
98 | as well as inside `convo.ask().` This would, for example, enable your bot to
99 | hear only intents instead of strings.
100 |
101 | ```javascript
102 | controller.changeEars(function(patterns, message) {
103 |
104 | // ... do something
105 | // return true or false
106 | });
107 | ```
108 |
109 |
110 | ### Heard Middleware
111 |
112 | Heard middleware can be used to modify or enrich a message with additional information before it is handled by the callback function.
113 | This can be useful for developers who want to use NLP tools, but want to limit the type and number of messages sent to be classified.
114 | It is also useful for developers who want to mix internal application data (for example, user account information) into messages.
115 |
116 | Whereas the `receive middleware` will fire for every single incoming message of any type, the heard middleware only fires when a pattern has already been matched.
117 |
118 | Heard middleware functions fire anytime Botkit attempts to match a pre-defined pattern: when using the `hears()` feature, and also when using `convo.ask()` to capture user responses.
119 |
120 |
121 | ```javascript
122 | controller.middleware.heard.use(function(bot, message, next) {
123 |
124 | // load internal user data and add it to the message
125 |
126 | mydb.users.find({id: message.user}, function(err, user_record) {
127 |
128 | // amend the message with a new field.
129 | // this will now be available inside the normal handler function
130 | message.internal_user = user_record;
131 |
132 | // call next or else execution will stall
133 | next();
134 |
135 | });
136 |
137 | });
138 | ```
139 |
140 | ### Capture Middleware
141 |
142 | As users respond to questions posed using `convo.ask()`, their answers will first be passed through any capture middleware endpoints.
143 | The capture middleware can modify the message in any way, including changing the value that will be used to test pre-defined patterns
144 | and that will ultimately be stored as the final user answer.
145 |
146 | This can be particularly useful when used in conjunction with a natural language processing API. NLP plugins like [IBM Watson](https://github.com/watson-developer-cloud/botkit-middleware) and [Microsoft LUIS](https://github.com/Stevenic/botkit-middleware-luis) typically provide 2 features: translation of raw user text into a pre-defined `intent`, and extraction of structured data from the raw string into `entities`.
147 |
148 | Another instance in which this is useful is when used in conjunction with buttons and quick replies that, in addition to displayed text may also carry a hidden payload value. Developers can use this middleware endpoint to capture the payload instead of the displayed text.
149 |
150 | The `capture` middleware endpoint allows developers to harness these values and capture them instead of or in addition to the raw user text.
151 |
152 | Please note that the signature of the `capture` middleware is slightly different than the other endpoints, as it includes a parameter for the conversation object:
153 |
154 | ```javascript
155 | controller.middleware.capture.use(function(bot, message, convo, next) {
156 |
157 | // user's raw response is in message.text
158 |
159 | // instead of capturing the raw response, let's capture the intent
160 | if (message.intent) {
161 | message.text = message.intent;
162 | }
163 |
164 | // what if there is a hidden payload? let's use that instead
165 | if (message.payload) {
166 | message.text = message.payload;
167 | }
168 |
169 | // what if there are entities too? we can use them as part of the conversation...
170 | if (message.entities) {
171 | for (var e = 0; e < message.entities.length; e++) {
172 | convo.setVar(message.entities[e].name, message.entities[e].value);
173 | }
174 | }
175 |
176 | // always call next!
177 | next();
178 |
179 | });
180 | ```
181 |
--------------------------------------------------------------------------------
/docs/provisioning/IMG/Slack-eventsenable.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/howdyai/botkit-docs/6569c40ec68762ae526cd2d4987765944f8c5cee/docs/provisioning/IMG/Slack-eventsenable.png
--------------------------------------------------------------------------------
/docs/provisioning/IMG/botkit_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/howdyai/botkit-docs/6569c40ec68762ae526cd2d4987765944f8c5cee/docs/provisioning/IMG/botkit_icon.png
--------------------------------------------------------------------------------
/docs/provisioning/IMG/cisco_add.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/howdyai/botkit-docs/6569c40ec68762ae526cd2d4987765944f8c5cee/docs/provisioning/IMG/cisco_add.png
--------------------------------------------------------------------------------
/docs/provisioning/IMG/fb_app_perm.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/howdyai/botkit-docs/6569c40ec68762ae526cd2d4987765944f8c5cee/docs/provisioning/IMG/fb_app_perm.png
--------------------------------------------------------------------------------
/docs/provisioning/IMG/fb_mess.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/howdyai/botkit-docs/6569c40ec68762ae526cd2d4987765944f8c5cee/docs/provisioning/IMG/fb_mess.png
--------------------------------------------------------------------------------
/docs/provisioning/IMG/fb_new.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/howdyai/botkit-docs/6569c40ec68762ae526cd2d4987765944f8c5cee/docs/provisioning/IMG/fb_new.png
--------------------------------------------------------------------------------
/docs/provisioning/IMG/fb_tokengen.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/howdyai/botkit-docs/6569c40ec68762ae526cd2d4987765944f8c5cee/docs/provisioning/IMG/fb_tokengen.png
--------------------------------------------------------------------------------
/docs/provisioning/IMG/fb_webhooks.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/howdyai/botkit-docs/6569c40ec68762ae526cd2d4987765944f8c5cee/docs/provisioning/IMG/fb_webhooks.png
--------------------------------------------------------------------------------
/docs/provisioning/IMG/fb_webhooks_com.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/howdyai/botkit-docs/6569c40ec68762ae526cd2d4987765944f8c5cee/docs/provisioning/IMG/fb_webhooks_com.png
--------------------------------------------------------------------------------
/docs/provisioning/IMG/slack-botuser.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/howdyai/botkit-docs/6569c40ec68762ae526cd2d4987765944f8c5cee/docs/provisioning/IMG/slack-botuser.png
--------------------------------------------------------------------------------
/docs/provisioning/IMG/slack-im.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/howdyai/botkit-docs/6569c40ec68762ae526cd2d4987765944f8c5cee/docs/provisioning/IMG/slack-im.png
--------------------------------------------------------------------------------
/docs/provisioning/IMG/slack-new.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/howdyai/botkit-docs/6569c40ec68762ae526cd2d4987765944f8c5cee/docs/provisioning/IMG/slack-new.png
--------------------------------------------------------------------------------
/docs/provisioning/IMG/slack_botevents.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/howdyai/botkit-docs/6569c40ec68762ae526cd2d4987765944f8c5cee/docs/provisioning/IMG/slack_botevents.png
--------------------------------------------------------------------------------
/docs/provisioning/IMG/slack_client_secret.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/howdyai/botkit-docs/6569c40ec68762ae526cd2d4987765944f8c5cee/docs/provisioning/IMG/slack_client_secret.png
--------------------------------------------------------------------------------
/docs/provisioning/IMG/slack_oauth.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/howdyai/botkit-docs/6569c40ec68762ae526cd2d4987765944f8c5cee/docs/provisioning/IMG/slack_oauth.png
--------------------------------------------------------------------------------
/docs/provisioning/cisco-spark.md:
--------------------------------------------------------------------------------
1 | # Configure Botkit and Cisco Webex Teams
2 |
3 | Setting up a bot for Cisco Webex Teams is one of the easiest experiences for bot developers! Follow these steps carefully to configure your bot.
4 |
5 | ### 1. Install Botkit
6 |
7 | You will need to [install Botkit](../readme-ciscospark.md#getting-started) and run it before your bot can be configured with Cisco Spark.
8 |
9 | ### 2. Create a new bot in the Cisco Developer portal
10 |
11 | Follow the instructions to create a new bot in the [Cisco Webex Teams Developer Portal](https://developer.ciscospark.com/add-bot.html).
12 |
13 | 
14 |
15 | Take note of the bot username, you'll need it later.
16 |
17 | **Note about your icon**: Cisco requires you host an avatar for your bot before you can create it in their portal. This bot needs to be a 512x512px image icon hosted anywhere on the web. This can be changed later.
18 |
19 | You can copy and paste this URL for a Botkit icon you can use right away:
20 |
21 | https://raw.githubusercontent.com/howdyai/botkit-starter-ciscospark/master/public/default_icon.png
22 |
23 | ### 3. Copy your access token
24 |
25 | Cisco will provide you an `access token` that is specific to your bot. Write this down, you won't be able to see this later (but you will be able revoke it and create a new one).
26 |
27 | ### 4. Run your bot with variables set
28 |
29 | [Follow these instructions](../readme-ciscospark.md#getting-started) to run your bot locally, or by using a third-party service such as [Glitch](https://glitch.com) or [Heroku](https://heroku.com).
30 |
31 | You will need the following environment variables when running your bot:
32 |
33 | * `access_token` = Your token from Webex Teams (**required**)
34 | * `secret` = User-defined string to validate payloads (**required**)
35 | * `public_address`= URL of your bot server (**required**)
36 |
37 | You should now be able to search your Webex Teams for the bot username you defined, and add it to your team!
38 |
39 | ### Additional resources
40 |
41 | Read more about making bots for this platform in the [Cisco Developer Portal](https://developer.ciscospark.com/bots.html).
42 |
--------------------------------------------------------------------------------
/docs/provisioning/facebook_messenger.md:
--------------------------------------------------------------------------------
1 | # Configure Botkit and Facebook Messenger
2 |
3 | *Note: This also applies for [Facebook Workplace](https://www.facebook.com/workplace)*
4 |
5 | Facebook is a constantly evolving platform, nominally you can find everything you [need to create a bot](https://developers.facebook.com/docs/messenger-platform/guides/quick-start) on their platform page, but that information is subject to change.
6 |
7 | You will need to [install Botkit](https://github.com/howdyai/botkit-starter-facebook) and run it before your bot can be configured with Messenger.
8 |
9 | ### 1. [Install Botkit](https://botkit.ai/getstarted.html)
10 |
11 | Once installed, you will need to do steps 2-4, and steps 5 in parallel. It helps to have your development enviroment and the Facebook for Developers page open at the same time.
12 |
13 | ### 2. Create a Facebook App for Web
14 |
15 | Visit [Facebook for Developers page](https://developers.facebook.com/tools-and-support/) and create a new app.
16 |
17 | 
18 |
19 | * Select a Messenger application
20 |
21 | 
22 |
23 | ### 3. Get a Page Access Token for your app
24 | Scroll down to `Token Generation`
25 |
26 | 
27 |
28 | If you have not yet created your page yet, you can go ahead and do this now, or associate this new bot with an existing page.
29 |
30 | Copy this `Page Access Token`, you'll need it when running your bot.
31 |
32 | ### 4. Setup webhooks
33 | Click `Setup Webhooks` to link this application to your Botkit instance.
34 |
35 | 
36 |
37 | The callback url will be `https://YOURURL/facebook/receive`. This URL must be publically available, and SSL-secured. More information on this can be found in the next step.
38 |
39 | You will also need to define a `Verify Token` for your page subscription. This is a user-defined string that you will keep secret and pass in with your environment variables.
40 |
41 | ### 5. Run your application
42 |
43 | Run your application with your environment variables set:
44 |
45 | * `page_token` - Your Page Access Token (**required**)
46 | * `verify_token` - Your Verify Token (**required**)
47 |
48 | If your application has been configured correctly, you will be able to talk to your bot through the page you specified in Step 3. Congratulations!
49 |
50 | ### Additional resources
51 | * [Botkit Facebook readme](/docs/readme-facebook.md)
52 | * [Botkit Facebook Starter Kit](https://github.com/howdyai/botkit-starter-facebook)
53 | * [Messenger Platform Documentation](https://developers.facebook.com/products/messenger/)
54 | * [Submit your bot so it can be publically available](https://developers.facebook.com/docs/messenger-platform/submission-process)
55 |
--------------------------------------------------------------------------------
/docs/provisioning/index.md:
--------------------------------------------------------------------------------
1 | # Provisioning Botkit
2 | As Botkit adds more platforms, it becomes increasingly difficult to keep track of all the methods for provisioning your bot on the various platforms we support.
3 |
4 | To help Botkit developers, we are pulling out detailed provisioning documents for each platform and keeping them in this directory. Our hope is that this will make our docs more flexible to platform changes, and clearly show the fastest way to stand up your bot!
5 |
6 | ## Platforms
7 |
8 | ### [Slack (Events API)](slack-events-api.md)
9 |
10 | ### [Microsoft Teams](teams.md)
11 |
12 | ### [Facebook Messenger](facebook_messenger.md)
13 |
14 | ### [Cisco Spark](cisco-spark.md)
15 |
16 | ### [SMS from Twilio](twilio-sms.md)
17 |
--------------------------------------------------------------------------------
/docs/provisioning/slack-events-api.md:
--------------------------------------------------------------------------------
1 | # Configure Botkit and the Slack Events API
2 |
3 | Building a bot with Botkit and the Slack Events API gives you access to all of the best tools and options available to create a feature-rich bot for Slack.
4 |
5 | In order to get everything set up, you will need to configure a new Slack App inside the [Slack Developer Portal](http://api.slack.com/apps), and at the same time, configure a [Botkit-powered bot](http://botkit.ai). It only takes a few moments, but there are a bunch of steps, so follow these instructions carefully.
6 |
7 | This feature is still in very active development at Slack, and these steps are subject to change.
8 |
9 | ## 1. Create a new Slack App
10 |
11 | Go to [http://api.slack.com/apps](http://api.slack.com/apps) and create a new application record.
12 |
13 | 
14 |
15 | You will receive a `clientId` and a `clientSecret`. You need these values - copy them into a temporary text file for use in the following steps.
16 |
17 | 
18 |
19 | ## 2. Turn on your Botkit app
20 |
21 | You will need to [install Botkit](../readme-slack.md#getting-started) and run it before your bot can be configured with Slack.
22 |
23 | Once you've collected your `clientId` and `clientSecret` tokens from Slack, you can start your Botkit app. You will need to have a bot service online and reachable over the web to complete the following steps and finish setting up your bot.
24 |
25 | ## 3. Configure OAuth
26 |
27 | Botkit and Slack use the OAuth authentication system to grant bots access to connect to, read from, and send messages to Slack teams.
28 |
29 | 
30 |
31 | Click on the "OAuth & Permissions" tab in your Slack's app setting, and under Redirect URLs, add: `https://my-bot-url/install/auth`, and save your progress.
32 |
33 | ## 4. Add a Bot User
34 |
35 | Click on the "Bot Users" tab and specify a name for your bot. This is the name that will be used by default when your application creates a new bot on a user's team.
36 |
37 | 
38 |
39 | In addition to a name, enable the option for "Always Show My Bot Online." This will ensure your Bot appears online to your team.
40 |
41 | ## 5. Set up Interactive Components
42 |
43 | "Interactive Components" is Slack's fancy way of saying "buttons, or dialogs, or menus." In order to enable these, under Request URL, add `https://YOURURL/api/messages`, then click save.
44 |
45 | 
46 |
47 | ## 6. Set up Event Subscriptions
48 |
49 | To start receiving messages, you will need to enable Event Subscriptions. Finally, scroll to the top of the page and switch "Enable Events" to "on".
50 |
51 | Next you will need to add your Request URL, like this: `https://YOURURL/api/messages`. When you finish typing, Slack will verify that this endpoint is properly configured. You must be running your Botkit application at the URL specified for this to work.
52 |
53 | 
54 |
55 | Once verified, click "Add Bot User Event", and using the dropdown that appears, select all of the `message.*` events:
56 |
57 | * `message.channels`
58 | * `message.groups`
59 | * `message.im`
60 | * `message.mpim`
61 |
62 | This configuration tells Slack to send your bot all messages that are sent in any channel or group in which your bot is present. Add other events as needed.
63 |
64 | 
65 |
66 | Your bot is now ready to receive messages!
67 |
68 | *Problems?* : If you do not see `Bot User` here, it is likely that you forgot to add a Bot User back in Step 4. Go and fix that now, and come back to Step 6 to continue.
69 |
70 | *Note*: If you intend on submitting to the App Directory, be sure to have a good reason to request more widely ranging events as your app can be rejected for excessively wide permissions.
71 |
72 | ## 7. Add your bot to your Slack team
73 |
74 | Now that your bot is configured, and your application is up and running, you can login and add your bot. Visit `https://MYURL/`, and you will be automatically directed to Slack's login page. Login and choose a team. You'll get one more confirmation before being redirected back to your app.
75 |
76 | Meanwhile, your bot should appear inside your Slack team. You should receive a friendly welcome message to indicates your bot is now online and working!
77 |
78 | ## Additional resources
79 | * [Botkit Slack readme](../readme-slack.md)
80 | * [Slack's official documention for Events API](https://api.slack.com/events-api)
81 |
--------------------------------------------------------------------------------
/docs/provisioning/teams.md:
--------------------------------------------------------------------------------
1 | # Configure Botkit and Microsoft Teams
2 | Building a bot with Botkit and the Microsoft Teams API gives you access to all of the best tools and options available to create a feature-rich app for Teams.
3 |
4 | We've created the following guide to help you configure your Microsoft Teams bot.
5 |
6 | ## Step 1 Register your bot with Bot Framework
7 | Microsoft Teams first requires you to register with their "Bot Framework" before you can add a bot to your Teams team. This is a multi-step process:
8 |
9 | ### Create an account / Log in
10 |
11 | Log into the [Bot Framework Developer Portal](https://dev.botframework.com/bots/) using your Microsoft credentials, or create an account.
12 |
13 | ### Register a new bot
14 | Once you are logged in, [click this link to create a new bot](https://dev.botframework.com/bots/new) and then you can skip the next two steps!
15 |
16 | * Click on `My Bots` and then Register. Choose `Create a bot with the Bot Builder SDK`, and click `Create`.
17 |
18 | * Select `Register an existing bot built using Bot Builder SDK` from the next menu and then click `OK`.
19 |
20 | You will be asked some questions about your bot. Some of these can be changed later, but some _cannot be changed_ so consider your responses carefully!
21 |
22 | These are the important fields when creating your bot:
23 |
24 | * `Display name` - Your bot's name in channels and directories. This can be changed later.
25 | * `Bot handle` - This will be used in the URL for your bot. *Note: This cannot be changed.*
26 | * `Messaging endpoint` - You may not know this yet, as you will be creating this in the next step when setting up the Botkit app. If you are using the [Botkit starter kit](https://github.com/howdyai/botkit-starter-teams), by default it is: `https://YOURURL/teams/receive`. Feel free to make anything up, you can come back later and change it.
27 |
28 | ### Generate your keys
29 | Register your bot with Microsoft by clicking: `Create Microsoft App ID and password`
30 |
31 | This action will take you to a new website (and require you to log in again) and then ask you for an `App name`.
32 |
33 | Once added, it will provide an `App ID` which you need to copy somewhere safe to use in the next step.
34 |
35 | Next, click `Generate password`. *This will only be shown to you once, if you lose it, you will need to invalidate the old one and set this up again!*
36 |
37 | Click Register.
38 |
39 | ### Add the Microsoft Teams channel
40 |
41 | Add the Microsoft Teams channel from the list of channels, making sure the `Enabled` is set to on.
42 |
43 | You will want to leave this window open as you finish setting up Botkit, as you will need to come back here before you are done.
44 |
45 | ## Step 4 - Deploy your bot and install to a team
46 |
47 | ### Turn on your Botkit app
48 | Now that everything is setup on Microsoft's side, you can [run Botkit](/docs/readme-teams.md#getting-started) using the method you've chosen and with the information created in the Bot framework in the previous step.
49 |
50 | ### Update your Messaging Endpoint in Bot Framework
51 | Once a Botkit instance is running, you may have a new URL that you will have to update in the bot's settings [in Microsoft Bot Framework](https://dev.botframework.com/bots/).
52 |
53 | Once logged in to that page:
54 |
55 | * Click on your bot
56 | * Select settings
57 | * Scroll down to the messaging endpoint field and replace the placeholder URL with your active Botkit URL (it should look something like `https://YOURURL/teams/receive`).
58 | * Click Save.
59 |
60 | ### Create your Application Manifest
61 | To add a development bot on a team, you will need to prepare an [App Package](https://msdn.microsoft.com/en-us/microsoft-teams/createpackage).
62 |
63 | ### Sideload your Bot to Microsoft Teams
64 | After creating your app package, you can [load it easily into your development team](https://msdn.microsoft.com/en-us/microsoft-teams/sideload#load-your-package-into-a-team).
65 |
66 | Say hello to your real live bot!
67 |
68 | ## Step 5 - Add dialogue and features
69 | Once you have a bot up and running, you can start the fun part of [making your bot functional](/docs/core.md#basic-usage).
70 |
71 | You can extend your bot's functionality using various [Botkit Middleware](/docs/middleware.md), or check our [example library](https://github.com/howdyai/botkit/tree/master/examples) for a good starting point.
72 |
73 | If you have questions or suggestions, please take a look at our [community support resources](core.md#developer--support-community). You can chat with contributors and enthusiasts in [our Slack community](https://community.botkit.ai/).
74 |
75 | ## Additional resources
76 | * [Botkit Microsoft Teams readme](/docs/readme-teams.md)
77 | * [Microsoft's Bot Framework](https://dev.botframework.com/)
78 |
--------------------------------------------------------------------------------
/docs/provisioning/twilio-sms.md:
--------------------------------------------------------------------------------
1 | # Configure Botkit and Twilio SMS
2 |
3 | Setting up a bot for Twilio SMS is one of the easiest experiences for bot developers! Follow these steps carefully to configure your bot.
4 |
5 | ### 1. Install Botkit
6 |
7 | You will need to [install Botkit](../readme-twiliosms.md#getting-started) and run it before your bot can be configured with Twilio SMS.
8 |
9 | ### 2. Create a new bot in the Twilio Developer Console
10 |
11 | Login and click `Get Started` in [Twilio SMS Developer Console](https://www.twilio.com/console/sms/dashboard). You will be taken through the process of obtaining a number to use with your bot.
12 |
13 | At this point you can use the Twilio wizard to help you create an application, or build one directly by clicking `Messanging Services`. You can give it a friendly, and chose `Mixed` for use case.
14 |
15 | Check the box `Process Inbound Messages` and under request URL, type the name of your request url.
16 |
17 | By default in Botkit, this is:
18 | https://*mybot.yoururl.com*/sms/receive
19 |
20 | ### 3. Collect your tokens
21 |
22 | Next, visit [your console Dashboard](https://www.twilio.com/console) and copy your `Account SID` and `Auth Token`. You will use these in the next step along with your assignedmobile number to setup Botkit.
23 |
24 | ### 4. Run your bot with variables set
25 |
26 | [Follow these instructions](../readme-twiliosms.md#getting-started) to run your bot locally, or by using a third-party service such as [Glitch](https://glitch.com) or [Heroku](https://heroku.com).
27 |
28 | You will need the following environment variables when running your bot:
29 |
30 | * TWILIO_ACCOUNT_SID= Your account's SID collected in step 3 above.
31 | * TWILIO_AUTH_TOKEN= Your account's Auth Token collected in step 3 above.
32 | * TWILIO_NUMBER= The number you were assigned in step 2 above.
33 |
34 | You should now be able to text message your number the words `Hello` and receive a friendly reply back!
35 |
36 | ### Additional resources
37 |
38 | Read more about making bots for this platform in the [Twilio Developer Portal](https://www.twilio.com/console).
39 |
--------------------------------------------------------------------------------
/docs/readme-botframework.md:
--------------------------------------------------------------------------------
1 | # Botkit and Microsoft Bot Framework
2 |
3 | The [Microsoft Bot Framework](https://botframework.com) makes it easy to create a single bot that can run across a variety of messaging channels including [Skype](https://skype.com), [Group.me](https://groupme.com), [Facebook Messenger](https://messenger.com), [Slack](https://slack.com),
4 | [Telegram](https://telegram.org/), [Kik](https://www.kik.com/), [SMS](https://www.twilio.com/), and [email](https://microsoft.office.com).
5 |
6 | Table of Contents
7 |
8 | * [Getting Started](#getting-started)
9 | * [Bot Framework Specific Events](#event-list)
10 | * [Working with the Bot Framework](#working-with-the-bot-framework)
11 | * [Sending Cards and Attachments](#sending-cards-and-attachments)
12 | * [Typing Indicator](#typing-indicator)
13 |
14 | ## Getting Started
15 |
16 | 1) Install Botkit [more info here](core.md#installation)
17 |
18 | 2) Register a developer account with the Bot Framework [Developer Portal](https://dev.botframework.com/) and follow [this guide](https://docs.botframework.com/en-us/csharp/builder/sdkreference/gettingstarted.html#registering) to register your first bot with the Bot Framework.
19 |
20 | * You'll be asked to provide an endpoint for your bot during the registration process which you should set to "https:///botframework/receive". If your using a service like [ngrok](https://ngrok.com/) to run your bot locally you should set the "" portion of your endpoint to
21 | be the hostname assigned by ngrok.
22 | * Write down the *App ID* and *App Password* assigned to your new bot as you'll need them when you run your bot.
23 |
24 | 3) By default your bot will be configured to support the Skype channel but you'll need to add it as a contact on Skype in order to test it. You can do that from the developer portal by clicking the "Add to Skype" button in your bots profile page.
25 |
26 | 4) Run the example bot using the App ID & Password you were assigned. If you are _not_ running your bot at a public, SSL-enabled internet address, use the --lt option and update your bots endpoint in the developer portal to use the URL assigned to your bot.
27 |
28 | ```
29 | app_id= app_password= node examples/botframework_bot.js [--lt [--ltsubdomain CUSTOM_SUBDOMAIN]]
30 | ```
31 |
32 | 5) Your bot should be online! Within Skype, find the bot in your contacts list, and send it a message.
33 |
34 | Try:
35 | * who are you?
36 | * call me Bob
37 | * shutdown
38 |
39 | ### Things to note
40 |
41 | Since the Bot Framework delivers messages via web hook, your application must be available at a public internet address. Additionally, the Bot Framework requires this address to use SSL. Luckily, you can use [LocalTunnel](https://localtunnel.me/) to make a process running locally or in your dev environment available in a Bot Framework friendly way.
42 |
43 | When you are ready to go live, consider [LetsEncrypt.org](http://letsencrypt.org), a _free_ SSL Certificate Signing Authority which can be used to secure your website very quickly.
44 |
45 | ## Create a controller
46 |
47 | To connect Botkit to Bot Framework, use the constructor method, [Botkit.facebookbot()](#botkit-facebookbot).
48 | This will create a Botkit controller with [all core features](core.md#botkit-controller-object) as well as [some additional methods](#additional-controller-methods).
49 |
50 | #### Botkit.botframeworkbot()
51 | | Argument | Description
52 | |--- |---
53 | | settings | Options used to configure the bot. Supports fields from [IChatConnectorSettings](https://docs.botframework.com/en-us/node/builder/chat-reference/interfaces/_botbuilder_d_.ichatconnectorsettings.html).
54 |
55 | Creates a new instance of the bots controller. The controller will create a new [ChatConnector](https://docs.botframework.com/en-us/node/builder/chat-reference/classes/_botbuilder_d_.chatconnector.html) so any options needed to configure the chat connector should be passed in via the `settings` argument.
56 |
57 | Generally speaking your bot needs to be configured with both an [appId](https://docs.botframework.com/en-us/node/builder/chat-reference/interfaces/_botbuilder_d_.ichatconnectorsettings.html#appid) and [appPassword](https://docs.botframework.com/en-us/node/builder/chat-reference/interfaces/_botbuilder_d_.ichatconnectorsettings.html#apppassword). You can leave these blank but then your bot can only be called by the [Bot Framework Emulator](https://docs.botframework.com/en-us/tools/bot-framework-emulator/#navtitle).
58 |
59 |
60 | ## Event List
61 |
62 | In addition to the [core events that Botkit fires](core.md#receiving-messages-and-events), this connector also fires some platform specific events.
63 |
64 | Normal messages will be sent to your bot using the `message_received` event. In addition, several other events may fire, depending on the channel your bot is configured to support.
65 |
66 | | Event | Description
67 | |--- |---
68 | | message_received | A message was received by the bot. Passed an [IMessage](https://docs.botframework.com/en-us/node/builder/chat-reference/interfaces/_botbuilder_d_.imessage.html) object.
69 | | conversationUpdate | Your bot was added to a conversation or other conversation metadata changed. Passed an [IConversationUpdate](https://docs.botframework.com/en-us/node/builder/chat-reference/interfaces/_botbuilder_d_.iconversationupdate.html) object.
70 | | contactRelationUpdate | The bot was added to or removed from a user's contact list. Passed an [IContactRelationUpdate](https://docs.botframework.com/en-us/node/builder/chat-reference/interfaces/_botbuilder_d_.icontactrelationupdate.html) object.
71 | | typing | The user or bot on the other end of the conversation is typing. Passed an [IEvent](https://docs.botframework.com/en-us/node/builder/chat-reference/interfaces/_botbuilder_d_.ievent.html) object.
72 |
73 | In addition to the event specific fields, all incoming events will contain both `user` and `channel` fields which can be used for things like storage keys. Every event also has an [address](https://docs.botframework.com/en-us/node/builder/chat-reference/interfaces/_botbuilder_d_.ievent.html#address) field. The `user` field is just a copy of the events `address.user.id` field and the `channel` field is a copy of the events `address.conversationId.id` field.
74 |
75 | Other notable fields for incoming messages are the [text](https://docs.botframework.com/en-us/node/builder/chat-reference/interfaces/_botbuilder_d_.imessage.html#text) field which contains the text of the incoming message, the [attachments](https://docs.botframework.com/en-us/node/builder/chat-reference/interfaces/_botbuilder_d_.imessage.html#attachments) field which would contain an array of any images sent to the bot by the user, the [source](https://docs.botframework.com/en-us/node/builder/chat-reference/interfaces/_botbuilder_d_.imessage.html#source) field which identifies the type of chat platform (facebook, skype, sms, etc.) that the bot is communicating over, and the [sourceEvent](https://docs.botframework.com/en-us/node/builder/chat-reference/interfaces/_botbuilder_d_.imessage.html#sourceevent) field containing the original event/message received from the chat platform.
76 |
77 | ## Working with the Bot Framework
78 |
79 | Botkit receives messages from the Bot Framework using webhooks, and sends messages to the Bot Framework using APIs. This means that your bot application must present a web server that is publicly addressable. Everything you need to get started is already included in Botkit.
80 |
81 | To connect your bot to the Bot Framework follow the step by step guide outlined in [Getting Started](#getting-started).
82 |
83 | Here is the complete code for a basic Bot Framework bot:
84 |
85 | ```javascript
86 | var Botkit = require('botkit');
87 | var controller = Botkit.botframeworkbot({
88 | });
89 |
90 | var bot = controller.spawn({
91 | appId: process.env.app_id,
92 | appPassword: process.env.app_password
93 | });
94 |
95 | // if you are already using Express, you can use your own server instance...
96 | // see "Use BotKit with an Express web server"
97 | controller.setupWebserver(process.env.port,function(err,webserver) {
98 | controller.createWebhookEndpoints(controller.webserver, bot, function() {
99 | console.log('This bot is online!!!');
100 | });
101 | });
102 |
103 | // user said hello
104 | controller.hears(['hello'], 'message_received', function(bot, message) {
105 |
106 | bot.reply(message, 'Hey there.');
107 |
108 | });
109 |
110 | controller.hears(['cookies'], 'message_received', function(bot, message) {
111 |
112 | bot.startConversation(message, function(err, convo) {
113 |
114 | convo.say('Did someone say cookies!?!!');
115 | convo.ask('What is your favorite type of cookie?', function(response, convo) {
116 | convo.say('Golly, I love ' + response.text + ' too!!!');
117 | convo.next();
118 | });
119 | });
120 | });
121 | ```
122 |
123 |
124 | #### controller.setupWebserver()
125 | | Argument | Description
126 | |--- |---
127 | | port | port for webserver
128 | | callback | callback function
129 |
130 | Setup an [Express webserver](http://expressjs.com/en/index.html) for
131 | use with `createWebhookEndpoints()`
132 |
133 | If you need more than a simple webserver to receive webhooks,
134 | you should by all means create your own Express webserver! Here is a [boilerplate demo](https://github.com/mvaragnat/botkit-messenger-express-demo).
135 |
136 | The callback function receives the Express object as a parameter,
137 | which may be used to add further web server routes.
138 |
139 | #### controller.createWebhookEndpoints()
140 |
141 | This function configures the route `https://_your_server_/botframework/receive`
142 | to receive webhooks from the Bot Framework.
143 |
144 | This url should be used when configuring Facebook.
145 |
146 | ## Sending Cards and Attachments
147 |
148 | One of the more complicated aspects of building a bot that supports multiple chat platforms is dealing with all the various schemes these platforms support. To help ease this development burden, the Bot Framework supports a cross platform card & attachment schema which lets you use a single JSON schema to express cards and attachments for any platform. The Bot Frameworks channel adapters will do their best to render a card on a given platform which sometimes result in a card being broken up into multiple messages.
149 |
150 | #### Sending Images & Files
151 |
152 | The frameworks [attachment schema](https://docs.botframework.com/en-us/node/builder/chat-reference/interfaces/_botbuilder_d_.iattachment.html) lets you send a single image/file using `contentType` and `contentUrl` fields:
153 |
154 | ```javascript
155 | bot.reply(message, {
156 | attachments: [
157 | {
158 | contentType: 'image/png',
159 | contentUrl: 'https://upload.wikimedia.org/wikipedia/en/a/a6/Bender_Rodriguez.png',
160 | name: 'Bender_Rodriguez.png'
161 | }
162 | ]
163 | });
164 | ```
165 |
166 | #### Sending Cards
167 |
168 | Rich cards can be expressed as attachments by changing the `contentType` and using the `content` field to pass a JSON object defining the card:
169 |
170 | ```javascript
171 | bot.reply(message, {
172 | attachments: [
173 | {
174 | contentType: 'application/vnd.microsoft.card.hero',
175 | content: {
176 | title: "I'm a hero card",
177 | subtitle: "Pig Latin Wikipedia Page",
178 | images: [
179 | { url: "https://" },
180 | { url: "https://" }
181 | ],
182 | buttons: [
183 | {
184 | type: "openUrl",
185 | title: "WikiPedia Page",
186 | value: "https://en.wikipedia.org/wiki/Pig_Latin"
187 | }
188 | ]
189 | }
190 | }
191 | ]
192 | });
193 | ```
194 |
195 | The full list of supported card types and relevant schema can be found [here](https://docs.botframework.com/en-us/csharp/builder/sdkreference/attachments.html)
196 |
197 | #### Using the Platforms Native Schema
198 |
199 | There may be times where the Bot Frameworks cross platform attachment schema doesn’t cover your needs. For instance, you may be trying to send a card type not directly supported by the framework. In those cases you can pass a message using the platforms native schema to the `sourceEvent` field on the message. Examples of this can be found [here](https://docs.botframework.com/en-us/csharp/builder/sdkreference/channels.html) (note: you should use `sourceEvent` instead of `channelData` and you don’t need to worry about the from & to fields, these will be populated for you when you call `bot.reply()`.)
200 |
201 | ## Typing Indicator
202 |
203 | You can easily turn on the typing indicator on platforms that support that behaviour by sending an empty message of type "typing":
204 |
205 | ```javascript
206 | bot.reply(message, { type: "typing" });
207 | ```
208 |
--------------------------------------------------------------------------------
/docs/readme-ciscojabber.md:
--------------------------------------------------------------------------------
1 | # Botkit for Cisco Jabber
2 |
3 | Botkit is designed to ease the process of designing and running useful, creative bots that live inside Cisco Jabber. Botkit features a comprehensive set of tools to deal with Cisco Jabber, and allows developers to build interactive bots and applications that send and receive messages just like real humans. This document covers the Cisco Jabber-specific implementation details only.
4 |
5 | ## Getting Started
6 |
7 | - Install Botkit
8 | - Ask admin to create a Jabber user for the bot in either Cisco IM&Presence Server (on-premise deployment) or Cisco Webex Messenger (cloud deployment), then get the jid and password from the admin. Jabber bots can send and receive messages, and in many cases, appear alongside their human counterparts as normal Jabber users.
9 |
10 | ## Working with Cisco Jabber
11 |
12 | Cisco Jabber bot uses node-xmpp to connect to Cisco Unified IM & Presence server or Cisco WebEx Messenger and can only use the password authentication methods. The bot is relying on starndard XMPP protocol to send/receive messages. You can refer to [RFC6120](https://tools.ietf.org/html/rfc6120) and [RFC6121](https://tools.ietf.org/html/rfc6121) to learn more about how to connect to XMPP server and how to create the XMPP message stanza.
13 |
14 | Cisco Jabber bot can take part in 1-1 chat or group chat conversations and can provide information or other services for the conversations. It's better to use persist store for the Botkit controller, otherwise when restart the bot, it will lose the group information and cannot received the message from a group chat.
15 |
16 | The full code for a simple Cisco Jabber bot is as below and you can find it in ../examples/jabber_bot.js:
17 |
18 | ```javascript
19 | const Botkit = require('./lib/JabberBot.js');
20 | var controller = Botkit({
21 | json_file_store: './bot_store/'
22 | });
23 | var bot = controller.spawn({
24 | client: {
25 | jid: 'xx@domain.com',
26 | password: *,
27 | host: "hostname.domain.com",
28 | port: 5222
29 | }
30 | });
31 | controller.hears(['hello'], ['direct_mention', 'direct_message'], function (bot, message) {
32 | bot.reply(message, 'Hi');
33 | });
34 | controller.on('direct_mention', function (bot, message) {
35 | bot.reply(message, 'You mentioned me in a group and said, "' + message.text + '"');
36 | });
37 | controller.on('direct_message', function (bot, message) {
38 | bot.reply(message, 'I got your direct message. You said, "' + message.text + '"');
39 | });
40 | ```
41 |
42 | ## Bot Options
43 |
44 | When spawn bot from the Botkit controller, there are several options available.
45 |
46 | Argument | Description
47 | -------- | -----------------------------------------------------------------------------------------------
48 | jid | Jid of the jabber bot
49 | password | Password of the jabber bot
50 | host | Host of the Cisco Unified IM & Presence server, not neccessary for bot of Cisco WebEx Messenger
51 | port | Port of the Cisco Unified IM & Presence server, not neccessary for bot of Cisco WebEx Messenger
52 |
53 | ## Jabber Specific Events
54 |
55 | Jabber support the following events
56 |
57 | Event | Description
58 | -------------- | -----------------------------------------------------------------------------------
59 | direct_message | Bot has received a direct message from a 1-1 chat
60 | direct_mention | Bot has received a message from a group chat and is mentioned by the message sender
61 | self_message | Bot has received a message it sent
62 |
63 | ## Message Formatting
64 |
65 | Cisco Jabber bot supports both plain text message and rich text message. Below is an example for plain text message.
66 |
67 | ```javascript
68 | bot.reply(message, 'Hello');
69 | ```
70 |
71 | Below is an example for rich text message. Jabber Bots Developer needs to compose the whole stanza for the message. He can create his own UI element to replace the UI part inside the body element in this example. Notes: Below example just for show element clearly. It's better to remove all empty space in the stanza.
72 |
73 | ```javascript
74 | let reply_message = {};
75 | let to = message.user;
76 | let type = message.group ? 'groupchat' : 'chat';
77 | let body = 'html demo(only for Jabber Windows now)';
78 | reply_message.text = body;
79 | reply_message.stanza = xml`${body}
80 |
81 |
82 |
83 |
84 | ${body}
85 |
89 |
90 |
91 |
92 |
93 | `;
94 | bot.reply(message, reply_message);
95 | ```
96 |
97 | Cisco Jabber can support all HTML5 elements and bootstrap 3.2 CSS style. However, Bot developer cannot inject any java-script code into the rich text message because of the security reason. In addition, Cisco Jabber introduces a new attribute robot-type for the button element to enhance the interaction between Jabber and the bot. Below is a short summary of the allow value and description. More detail and example usage can be found in later section.
98 |
99 | Value | Description
100 | -------------------- | ------------------------------------------------------------------------------------------------------
101 | robot-button | Send back a message
102 | robot-openlink | Open URL
103 | robot-executecommand | Execute predefined command in Jabber, like start group chat, start conf call and start instant meeting
104 | robot-submit | Send back a json message with all input name and value in a HTML form.
105 |
106 | - When value is robot-button, when user clicks the button, Jabber will send back a message defined in the attribute robot-message in the same element. Below is an example
107 |
108 | ```javascript
109 | let reply_message = {};
110 | let to = message.user;
111 | let type = message.group ? 'groupchat' : 'chat';
112 | let body = 'robot-button demo(only for Jabber Windows)';
113 | reply_message.text = body;
114 | reply_message.stanza = xml`${body}
115 |
${body}
`;
116 | bot.reply(message, reply_message);
117 | ```
118 |
119 | All the below buttons needs to be putted in a form.
120 |
121 | - When value is robot-openlink, when user clicks the button, cisco jabber will find an element name with openlink in the form, and open URL defined in value of the element name with openlink. Below is an example
122 |
123 | ```javascript
124 | let reply_message = {};
125 | let to = message.user;
126 | let type = message.group ? 'groupchat' : 'chat';
127 | let body = 'robot-openlink demo(only for Jabber Windows)';
128 | reply_message.text = body;
129 | reply_message.stanza = xml`${body}
130 |
131 |
${body}
132 |
138 |
139 | `;
140 | bot.reply(message, reply_message);
141 | ```
142 |
143 | - When value is robot-executecommand, when user clicks the button, cisco jabber will find an element name with command in the form, and execute command defined in value of the element name with command. Jabber provide 3 kinds of command as below examples to start group chat, start an audio/video conference and start an instant Webex meeting. startgroupchat:john@cisco.com;mick@cisco.com startconference:john@cisco.com;mick@cisco.com startmeeting:john@cisco.com;mick@cisco.com Below is an example, jabber need the jid to execute the related action, generally we can extract the jid from the message received from the user, function extractMentionJids is used to help extract @mention jid from the message.
144 |
145 | ```javascript
146 | function extractMentionJids(message) {
147 | let direct_mention_reg = /href="xmpp:\s?(\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+)\s?"/ig;
148 | let email_reg = /\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+/i;
149 | let match = message.stanza.toString().match(direct_mention_reg);
150 | let mention_jids = [];
151 | if (match) {
152 | for (let i = 0; i < match.length; i++) {
153 | let jid_match = match[i].match(email_reg);
154 | if (jid_match) {
155 | let jid = jid_match[0];
156 | if (jid != bot.client_jid) {
157 | mention_jids.push(jid);
158 | }
159 | }
160 | }
161 | }
162 | return mention_jids;
163 | }
164 |
165 | let reply_message = {};
166 | let to = message.user;
167 | let type = message.group ? 'groupchat' : 'chat';
168 | let mention_jids = extractMentionJids(message);
169 | let mentionJids = "";
170 | for (let i = 0; i < mention_jids.length; i++) {
171 | mentionJids += mention_jids[i];
172 | mentionJids += ";";
173 | }
174 |
175 | let body = 'robot-executecommand demo(only for Jabber Windows)';
176 | reply_message.text = body;
177 | reply_message.stanza = xml`${body}
178 |
179 |
${body}
180 |
186 |
187 |
188 |
194 |
195 |
196 |
202 |
203 | `;
204 | bot.reply(message, reply_message);
205 | ```
206 |
207 | - When value is robot-submit, click the button, cisco jabber will find all element name in the form, and combine all the input into a JSON message and then send it back to the bot. Below is an example
208 |
209 | ```javascript
210 | let reply_message = {};
211 | let to = message.user;
212 | let type = message.group ? 'groupchat' : 'chat';
213 |
214 | let body = 'robot-submit demo(only for Jabber Windows)';
215 | reply_message.text = body;
216 | reply_message.stanza = xml`${body}
217 |
218 |
Please enter the meeting information:
219 |
282 |
283 | `;
284 |
285 | bot.startConversation(message, function (err, convo) {
286 | if (!err) {
287 | convo.ask(reply_message, function (response, convo) {
288 | try {
289 | if (response.from_jid == bot.client_jid) {
290 | return;
291 | }
292 | let query = JSON.parse(response.text);
293 |
294 | let replay_meeting_info = "You submit the following information:";
295 | replay_meeting_info += "Required Attendees:" + query.required_attendees + ";";
296 | replay_meeting_info += "Subject:" + query.subject + ";";
297 | replay_meeting_info += "Body:" + query.body + ";";
298 | replay_meeting_info += "Topics:" + query.topics + ";";
299 | replay_meeting_info += "Location:" + query.location + ";";
300 | replay_meeting_info += "Start:" + query.start + ";";
301 | replay_meeting_info += "End:" + query.end + "";
302 | bot.reply(message, replay_meeting_info);
303 | convo.stop();
304 | }
305 | catch (err) {
306 | console.log(err.message);
307 | convo.stop();
308 | }
309 | });
310 | }
311 | });
312 | ```
313 |
314 | ## Extensible Messaging and Presence Protocol – API for jabber bot
315 |
316 | Jabber bot uses node-xmpp to connect to Cisco Unified IM & Presence server or Cisco WebEx Messenger and can only use the password authentication methods. The bot is relying on starndard XMPP protocol to send/receive messages. You can refer to [RFC6120](https://tools.ietf.org/html/rfc6120) and [RFC6121](https://tools.ietf.org/html/rfc6121) to learn more about how to connect to XMPP server and how to create the XMPP message stanza. Below is an example for an xmpp message stanza with HTML payload. The bot developer can use this kind of message stanza to implement the functions.
317 |
318 | ```html
319 |
325 | Art thou not Romeo, and a Montague?
326 |
327 |
328 |
329 | Art thou not Romeo, and a Montague?
330 |
331 |
332 |
333 | ```
334 |
335 | JabberBot uses node-simple-xmpp to build connection and exchange message with Cisco Unified IM & Presence server or Cisco WebEx Messenger. If you would like to have more functions from XMPP, you can integrate more function into jabber_bot.js with the help of node-simple-xmpp and the underlying node-xmpp like what we have done in the JabberGroupManager.js. Just handle stanza and underlying events, the bot can have all the functions that a xmpp client can do.
336 |
--------------------------------------------------------------------------------
/docs/readme-ciscospark.md:
--------------------------------------------------------------------------------
1 | # Botkit and Cisco Webex Teams
2 |
3 | *Note: Cisco Spark is [now Cisco Webex Teams](https://blogs.cisco.com/collaboration/webex-platform-convergence?_ga=2.75241682.1559193461.1524070554-1809816543.1524070554). Versions of Botkit from 0.6.17 onward refer to [Webex](readme-webex.html).
4 |
5 | Table of Contents
6 |
7 | * [Getting Started](#getting-started)
8 | * [Create a Controller](#create-a-controller)
9 | * [Webex Teams-specific Events](#event-list)
10 | * [Message Formatting](#message-formatting)
11 | * [Attaching Files](#attaching-files)
12 | * [Receiving Files](#receiving-files)
13 | * [Starting Direct Messages](#starting-direct-messages)
14 |
15 |
16 | ## Getting Started
17 |
18 | 1. [Install Botkit on your computer](/getstarted.html)
19 |
20 | 2. Create a Botkit powered Node app:
21 |
22 | * [Remix the starter project on Glitch](https://glitch.com/~botkit-cisco-webex-teams)
23 | * Or: Use the command line tool:
24 |
25 | ```
26 | botkit new --platform spark
27 | ```
28 |
29 | 3. [Follow this guide to configuring the Cisco Webex Teams API](/docs/provisioning/cisco-spark.md)
30 |
31 |
32 |
33 | ## Working with Webex Teams
34 |
35 | Botkit receives messages from Webex Teams using webhooks, and sends messages using their APIs. This means that your bot application must present a web server that is publicly addressable. Everything you need to get started is already included in Botkit.
36 |
37 | To connect your bot to Webex Teams, [get an access token here](https://developer.ciscospark.com/add-bot.html). In addition to the access token,
38 | Webex Teams bots require a user-defined `secret` which is used to validate incoming webhooks, as well as a `public_address` which is the URL at which the bot application can be accessed via the internet.
39 |
40 | Each time the bot application starts, Botkit will register a webhook subscription.
41 | Botkit will automatically manage your bot's webhook subscriptions, but if you plan on having multiple instances of your bot application with different URLs (such as a development instance and a production instance), use the `webhook_name` field with a different value for each instance.
42 |
43 | Bots in Webex Teams are identified by their email address, and can be added to any space in any team or organization. If your bot should only be available to users within a specific organization, use the `limit_to_org` or `limit_to_domain` options.
44 | 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.
45 |
46 | The full code for a simple Webex Teams bot is below:
47 |
48 | ```javascript
49 | var Botkit = require('./lib/Botkit.js');
50 |
51 | var controller = Botkit.sparkbot({
52 | debug: true,
53 | log: true,
54 | public_address: process.env.public_address,
55 | ciscospark_access_token: process.env.access_token,
56 | secret: process.env.secret
57 | });
58 |
59 | var bot = controller.spawn({
60 | });
61 |
62 | controller.setupWebserver(process.env.PORT || 3000, function(err, webserver) {
63 | controller.createWebhookEndpoints(webserver, bot, function() {
64 | console.log("SPARK: Webhooks set up!");
65 | });
66 | });
67 |
68 | controller.hears('hello', 'direct_message,direct_mention', function(bot, message) {
69 | bot.reply(message, 'Hi');
70 | });
71 |
72 | controller.on('direct_mention', function(bot, message) {
73 | bot.reply(message, 'You mentioned me and said, "' + message.text + '"');
74 | });
75 |
76 | controller.on('direct_message', function(bot, message) {
77 | bot.reply(message, 'I got your private message. You said, "' + message.text + '"');
78 | });
79 | ```
80 |
81 | ## Create a Controller
82 |
83 | To connect Botkit to Webex Teams, use the Spark constructor method, [Botkit.sparkbot()](#botkitsparkbot).
84 | This will create a Botkit controller with [all core features](core.md#botkit-controller-object) as well as [some additional methods](#additional-controller-methods).
85 |
86 | #### Botkit.sparkbot()
87 | | Argument | Description
88 | |--- |---
89 | | studio_token | String | An API token from [Botkit Studio](#readme-studio.md)
90 | | debug | Boolean | Enable debug logging
91 | | public_address | _required_ the root url of your application (https://mybot.com)
92 | | `ciscospark_access_token` | _required_ token provided by Webex Teams for your bot
93 | | secret | _required_ secret for validating webhooks originate from Webex Teams
94 | | webhook_name | _optional_ name for webhook configuration on Webex Teams side. Providing a name here allows for multiple bot instances to receive the same messages. Defaults to 'Botkit Firehose'
95 | | `limit_to_org` | _optional_ organization id in which the bot should exist. If user from outside org sends message, it is ignored
96 | | `limit_to_domain` | _optional_ email domain (@howdy.ai) or array of domains [@howdy.ai, @botkit.ai] from which messages can be received
97 |
98 | ```javascript
99 | var controller = Botkit.sparkbot({
100 | debug: true,
101 | log: true,
102 | public_address: 'https://mybot.ngrok.io',
103 | ciscospark_access_token: process.env.access_token,
104 | secret: 'randomstringofnumbersandcharacters12345',
105 | webhook_name: 'dev',
106 | limit_to_org: 'my_spark_org_id',
107 | limit_to_domain: ['@howdy.ai','@cisco.com'],
108 | });
109 | ```
110 |
111 | ## Event List
112 |
113 | In addition to the [core events that Botkit fires](core.md#receiving-messages-and-events), this connector also fires some platform specific events.
114 |
115 | All events [listed here](https://developer.ciscospark.com/webhooks-explained.html#resources-events) should be expected, in the format `resource`.`event` - for example, `rooms.created`.
116 |
117 | ### Incoming Message Events
118 | | Event | Description
119 | |--- |---
120 | | direct_message | Bot has received a message as a DM
121 | | direct_mention | Bot has been mentioned in a public space
122 | | self_message | Bot has received a message it sent
123 |
124 | ### User Activity Events:
125 | | Event | Description
126 | |--- |---
127 | | user_space_join | a user has joined a space in which the bot is present
128 | | bot_space_join | the bot has joined a new space
129 | | user_space_leave | a user has left a space in which the bot is present
130 | | bot_space_leave | the bot has left a space
131 |
132 |
133 | ## Message Formatting
134 |
135 | Webex Teams supports both a `text` field and a `markdown` field for outbound messages. [Read here for details on Webex Teams's markdown support.](https://developer.ciscospark.com/formatting-messages.html)
136 |
137 | To specify a markdown version, add it to your message object:
138 |
139 | ```javascript
140 | bot.reply(message,{text: 'Hello', markdown: '*Hello!*'});
141 | ```
142 |
143 | ## Attaching Files
144 |
145 | Files can be attached to outgoing messages in one of two ways.
146 |
147 | *Specify URL*
148 |
149 | If the file you wish to attach is already available online, simply specify the URL in the `files` field of the outgoing message:
150 |
151 | ```javascript
152 | bot.reply(message,{text:'Here is your file!', files:['http://myserver.com/file.pdf']});
153 | ```
154 |
155 | *Send Local File*
156 |
157 | If the file you wish to attach is present only on the local server, attach it to the message as a readable stream:
158 |
159 | ```javascript
160 | var fs = require('fs');
161 | bot.reply(message,{text: 'I made this file for you.', files:[fs.createReadStream('./newfile.txt')]});
162 | ```
163 |
164 | ## Receiving files
165 |
166 | Your bot may receive messages with files attached. Attached files will appear in an array called `message.original_message.files`.
167 |
168 | Botkit provides 2 methods for retrieving information about the file.
169 |
170 | ### bot.retrieveFileInfo(url, cb)
171 | | Parameter | Description
172 | |--- |---
173 | | url | url of file from message.original_message.files
174 | | cb | callback function in the form function(err, file_info)
175 |
176 | The callback function will receive an object with fields like `filename`, `content-type`, and `content-length`.
177 |
178 | ```javascript
179 | controller.on('direct_message', function(bot, message) {
180 | bot.reply(message, 'I got your private message. You said, "' + message.text + '"');
181 | if (message.original_message.files) {
182 | bot.retrieveFileInfo(message.original_message.files[0], function(err, file_info) {
183 | bot.reply(message,'I also got an attached file called ' + file_info.filename);
184 | });
185 | }
186 | });
187 | ```
188 |
189 | ### bot.retrieveFile(url, cb)
190 | | Parameter | Description
191 | |--- |---
192 | | url | url of file from message.original_message.files
193 | | cb | callback function in the form function(err, file_content)
194 |
195 | The callback function will receive the full content of the file.
196 |
197 | ```javascript
198 | controller.on('direct_message', function(bot, message) {
199 | bot.reply(message, 'I got your private message. You said, "' + message.text + '"');
200 | if (message.original_message.files) {
201 | bot.retrieveFileInfo(message.original_message.files[0], function(err, file_info) {
202 | if (file_info['content-type'] == 'text/plain') {
203 | bot.retrieveFile(message.original_message.files[0], function(err, file) {
204 | bot.reply(message,'I got a text file with the following content: ' + file);
205 | });
206 | }
207 | });
208 | }
209 | });
210 | ```
211 |
212 | ## Starting Direct Messages
213 |
214 | Webex Teams's API provides several ways to send private messages to users -
215 | by the user's email address, or by their user id. These may be used in the case where the
216 | user's email address is unknown or unavailable, or when the bot should respond to the `actor`
217 | instead of the `sender` of a message.
218 |
219 | For example, a bot may use these methods when handling a `bot_space_join` event
220 | in order to send a message to the _user who invited the bot_ (the actor) instead of
221 | the bot itself (the sender).
222 |
223 | NOTE: Core functions like [bot.startPrivateConversation()](core.md#botstartprivateconversation) work as expected,
224 | and will create a direct message thread with the sender of the incoming_message.
225 |
226 | ### bot.startPrivateConversationWithPersonId()
227 | | Parameter | Description
228 | |--- |---
229 | | personId | the personId of the user to whom the bot should send a message
230 | | cb | callback function in the form function(err, file_content)
231 |
232 | Use this function to send a direct message to a user by their personId, which
233 | can be found in message and event payloads at the following location:
234 |
235 | ```javascript
236 | var personId = message.original_message.actorId;
237 | ```
238 |
239 | ### bot.startPrivateConversationWithActor())
240 | | Parameter | Description
241 | |--- |---
242 | | incoming_message | a message or event that has an actorId defined in message.original_message.actorId
243 | | cb | callback function in the form function(err, file_content)
244 |
245 | ```javascript
246 | controller.on('bot_space_join', function(bot, message) {
247 | bot.startPrivateConversationWithActor(message, function(err, convo) {
248 | convo.say('The bot you invited has joined the channel.');
249 | });
250 | });
251 | ```
252 |
253 |
254 | # Additional Controller methods
255 |
256 | #### controller.createWebhookEndpoints()
257 |
258 | #### controller.resetWebhookSubscriptions()
259 |
260 | #### controller.handleWebhookPayload()
261 |
262 | # Join the Cisco Webex Teams Bokit developer channel.
263 | Cisco hosts a Botkit Developer team [over on their public webex team channel](https://eurl.io/#SyNZuomKx). You can pop in here if you have questions about developing for Webex teams.
264 |
--------------------------------------------------------------------------------
/docs/readme-google-hangouts.md:
--------------------------------------------------------------------------------
1 | # Botkit and Google Hangouts
2 |
3 | Table of Contents
4 |
5 | * [Getting Started](#getting-started)
6 | * [Things to note](#things-to-note)
7 | * [Create a Controller](#create-a-controller)
8 | * [Event List](#event-list)
9 |
10 | ## Getting Started
11 |
12 | 1. [Install Botkit on your computer](/getstarted.html)
13 |
14 | 2. Create a Botkit powered Node app:
15 |
16 | * [Remix the starter project on Glitch](https://glitch.com/~botkit-hangouts)
17 | * Or: Use the command line tool:
18 |
19 | ```
20 | botkit new --platform googlehangouts
21 | ```
22 |
23 | ## Things to note
24 |
25 | Hangouts Chat supports team collaboration by providing:
26 |
27 | - Chat rooms that let you dedicate discussion space on a per-project, per-team, or other basis as appropriate
28 | - Threaded conversations within rooms
29 | - Direct messages between users
30 | - Bots that can participate in rooms or respond to direct messages
31 |
32 | Hangouts Chat communicates with your bot via an HTTP endpoint, you must specify an endpoint in the Chat API configuration tab when you publish your bot.
33 |
34 |
35 | ## Create a Controller
36 |
37 | To connect Botkit to Google Hangouts, use the constructor method, [Botkit.googlehangoutsbot()](#googlehangoutsbot).
38 | This will create a Botkit controller with [all core features](core.md#botkit-controller-object) as well as [some additional methods](#additional-controller-methods).
39 |
40 | #### Botkit.googlehangoutsbot()
41 | | Argument | Description
42 | |--- |---
43 | | config | an object containing configuration options
44 |
45 | Returns a new Botkit controller.
46 |
47 | The `config` argument is an object with these properties:
48 |
49 | | Name | Type | Description
50 | |--- |--- |---
51 | | studio_token | String | An API token from [Botkit Studio](#readme-studio.md)
52 | | debug | Boolean | Enable debug logging
53 | | endpoint | string | Bot endpoint link
54 | | token| string | to verify bot authenticity
55 |
56 |
57 | For example:
58 |
59 | ```javascript
60 | var Botkit = require('botkit');
61 | var controller = Botkit.googlehangoutsbot({
62 | endpoint: 'YOUR_ENDPOINT',
63 | token: "YOUR_TOKEN"
64 | });
65 | ```
66 |
67 |
68 | ## Event List
69 |
70 | In addition to the [core events that Botkit fires](core.md#receiving-messages-and-events), this connector also fires some platform specific events.
71 |
72 | ### Incoming Events
73 |
74 | | Event | Description
75 | |--- |---
76 | | message_received | The bot received a direct message from a user
77 | | direct_message | This event indicates that your bot was added to a DM
78 | | bot_room_join | This event indicates that your bot was added to a shared room
79 | | bot_room_leave | This event indicates that your bot was removed from a shared room
80 | | bot_dm_join | This event indicates that your bot was added to a 1:1
81 | | bot_dm_leave | This event indicates that your bot was removed from a 1:1
82 | | card_clicked | The bot received a card click
83 |
84 | Here's an example on how to handler incoming events :
85 |
86 | ```javascript
87 | controller.hears('hello', 'message_received', function (bot, message) { ... });
88 | controller.hears('hi', 'direct_message', function (bot, message) { ... });
89 | controller.on('bot_room_leave', function (bot, message) { ... });
90 | controller.on('card_clicked', function (bot, message) { ... });
91 | ```
92 | ## Send simple text messages
93 |
94 | These messages are displayed like any other chat message. They can include simple character formatting.
95 |
96 | [Learn more about simple text messages](https://developers.google.com/hangouts/chat/reference/message-formats/basic)
97 |
98 | #### bot.reply()
99 |
100 | | Argument | Description
101 | |--- |---
102 | | src | source message as received from google
103 | | reply | reply message (string or object)
104 | | callback | optional callback
105 |
106 | This function sends an immediate response that is visible to everyone in the channel:
107 |
108 | ```javascript
109 | bot.reply(message, `Hello`);
110 | bot.reply(message, {text : `Hi !`});
111 | ````
112 |
113 | #### bot.replyWithThreadKey()
114 |
115 | | Argument | Description
116 | |--- |---
117 | | src | source message as received from google
118 | | reply | reply message (string or object)
119 | | callback | optional callback
120 |
121 | To send a message as a reply in an existing thread:
122 |
123 | ```javascript
124 | bot.replyWithThreadKey(message, {
125 | threadKey : "YOUR_THREAD_KEY",
126 | requestBody : {
127 | text : `Hi ! this message inside the same thread`
128 | }
129 | });
130 | ````
131 |
132 | #### bot.replyAsNewThread()
133 |
134 | | Argument | Description
135 | |--- |---
136 | | src | source message as received from google
137 | | reply | reply message (string or object)
138 | | callback | optional callback
139 |
140 | To send a message into Hangouts Chat as a new thread:
141 |
142 | ```javascript
143 | bot.replyAsNewThread(message, `Hello ! this is a new thread`);
144 | ````
145 |
146 | ## Send card messages
147 |
148 | These messages contain all the details that Hangouts Chat needs to render a card in the chat room. These details include any text, special formatting, widgets, and other details used in the card.
149 |
150 | [Learn more about card messages](https://developers.google.com/hangouts/chat/reference/message-formats/cards)
151 |
152 |
153 | ```javascript
154 | controller.hears('cards', 'message_received', function (bot, message) {
155 | bot.reply(message, {
156 | requestBody: {
157 | cards: [
158 | {
159 | "sections": [
160 | {
161 | "widgets": [
162 | {
163 | "image": { "imageUrl": "https://image.slidesharecdn.com/botkitsignal-160526164159/95/build-a-bot-with-botkit-1-638.jpg?cb=1464280993" }
164 | },
165 | {
166 | "buttons": [
167 | {
168 | "textButton": {
169 | "text": "Get Started",
170 | "onClick": {
171 | "openLink": {
172 | "url": "https://botkit.ai/docs/"
173 | }
174 | }
175 | }
176 | }
177 | ]
178 | }
179 | ]
180 | }
181 | ]
182 | }
183 | ]
184 | }
185 | });
186 | });
187 | ```
188 |
--------------------------------------------------------------------------------
/docs/readme-middlewares.md:
--------------------------------------------------------------------------------
1 | # Botkit middlewares
2 |
3 | The functionality of Botkit can be extended using middleware functions. These functions can plugin to the core bot running processes at several useful places and make changes to both a bot's configuration and the incoming or outgoing message. Anyone can add their own middleware to the Botkit documentation, [for more information please read this.](#have-you-created-middleware)
4 |
5 | Currently the following types of middleware are available for Botkit:
6 | ### [Natural language processing](#natural-language-processing)
7 | Natural language processing allows for bots to understand conversational human inputs and interprets your users desires into actionable functions of your application. Once properly trained, these add-ons can dramatically improve the UX for your bot application.
8 |
9 | ### [Storage Modules](#storage-modules-1)
10 | Storage middleware can be used for storing attributes about a user or channel or team. Botkit supports most major storage methods.
11 |
12 | ### [Statistics, Metrics, and CRM](#statistics-metrics-and-crm-1)
13 | These plugins help you measure the success of your bots, across a variety of measurable methods.
14 |
15 | ## Official Botkit Extensions
16 | Name | Project PAge | Info |
17 | | ------ | ------ | ------ |
18 | | Botkit CMS | https://github.com/howdyai/botkit-cms | An open tool for designing, building and managing interactive dialog systems |
19 |
20 |
21 | ## Natural Language Processing
22 |
23 | Name | Project Page | Info |
24 | | ------ | ------ | ------ |
25 | | Microsoft Luis | https://github.com/Stevenic/botkit-middleware-luis | The Luis middleware with Botkit causes every message sent to your bot to be first sent through Luis.ai's NLP services for processing.
|
26 | | Amazon Lex | https://github.com/jonchurch/botkit-middleware-lex | This middleware allows you to send user input to AWS Lex. This gives you access to intent mapping, data slots, NLP, and other capabilities of the Lex service. You can use this middleware to extend your bots capabilities, add an interaction that lives in Lex to an existing bot, or to run a Lex bot with Botkit as the connector. |
27 | | Google Dialogflow | https://github.com/jschnurr/botkit-middleware-dialogflow | This middleware plugin for Botkit allows you to utilize Dialogflow (formerly Api.ai), a natural language classifier service directly into the Botkit corebot.
|
28 | | IBM Watson | https://github.com/watson-developer-cloud/botkit-middleware | This middleware plugin for Botkit allows developers to easily integrate a Watson Conversation workspace with multiple social channels like Slack, Facebook, and Twilio. Customers can have simultaneous, independent conversations with a single workspace through different channels.
|
29 | | Recast.ai | https://github.com/ouadie-lahdioui/botkit-middleware-recastai | You can use the Recast.AI API to analyse your text or your audio file, and extract useful information from it, to personalize your IoT, classify your data or create bots.
|
30 | | Wit.ai | https://github.com/howdyai/botkit-middleware-witai | Wit.ai provides a service that uses machine learning to help developers handle natural language input. The Wit API receives input from the user, and translates it into one or more "intents" which map to known actions or choices. The power of Wit is that it can continually be trained to understand more and more responses without changing the underlying bot code!
|
31 | | Rasa | https://github.com/howdyai/botkit-rasa | This plugin provides Botkit developers a way to use the rasa NLU open source, self hosted natural language API.
|
32 |
33 | ## Utilities
34 | | Name | Project Page | Info |
35 | | ------ | ------ | ------ |
36 | | Janis | https://github.com/Janis-ai/npm-janis | Janis is an AI management toolkit that enables teams working in Slack to collaborate on AI training, monitor bots for problems, and quickly resolve and prevent business-impacting incidents. |
37 | | Facebook | https://github.com/pinkku/botkit-middleware-facebookuser | This plugin allows you to collect Facebook Messenger user info to populate a Botkit message
|
38 |
39 | ## Storage Modules
40 | | Name | Project Page | Info |
41 | | ------ | ------ | ------ |
42 | | Mongo | https://github.com/howdyai/botkit-storage-mongo | A Mongo storage module for Botkit |
43 | | Redis | https://github.com/howdyai/botkit-storage-redis | A redis storage module for Botkit |
44 | | Datastore | https://github.com/fabito/botkit-storage-datastore | A Google Cloud Datastore storage module for Botkit |
45 | | Firestore | https://github.com/shishirsharma/botkit-storage-firestore | A Firestore storage module for Botkit. |
46 | | Firebase | https://github.com/howdyai/botkit-storage-firebase | A Firebase storage module for Botkit. |
47 | | Postgres | https://github.com/lixhq/botkit-storage-postgres | Postgres storage module for Botkit |
48 | | CouchDB | https://github.com/mbarlock/botkit-storage-couchdb/ | A Couchdb storage module for botkit |
49 | | MySQL | https://github.com/getforgex/botkit-storage-mysql/ | A MySQL storage module for botkit |
50 |
51 |
52 | ## Statistics, Metrics, and CRM
53 |
54 | | Name | Project Page | Info |
55 | | ------ | ------ | ------ |
56 | | Chatbase | https://github.com/asopinka/chatbase-botkit | A middleware package for Botkit that easily logs your convos in Chatbase|
57 | | Dashbot Slack | https://www.dashbot.io/sdk/slack/botkit | Increase user engagement, acquisition, and monetization through actionable bots analytics. |
58 | | Dashbot Facebook | https://www.dashbot.io/sdk/facebook/botkit | Increase user engagement, acquisition, and monetization through actionable bots analytics. |
59 | | Keen | https://github.com/keen/keen-botkit | This middleware allows you to to understand how many messages are going through your system, run cohorts to measure retention, set up funnels to measure task completion, and any key metric unique to your bot. More information about the Keen platform can be found on their website |
60 | | Mixpanel | https://github.com/shishirsharma/botkit-mixpanel |This module enables the basic Mixpanel analytics. With this module installed and enabled, your Botkit application will automatically send a copy of any message your bot receives to Mixpanel's analytics API, as well as user profile information. |
61 |
62 | # Have you created middleware?
63 | We would love to hear about it! [Contact the Howdy team](https://howdy.ai/) to be included in Botkit documentation, or [submit a PR on this documentation](https://github.com/howdyai/botkit-storage-firebase/blob/master/CONTRIBUTING.md)!
64 |
--------------------------------------------------------------------------------
/docs/readme-pipeline.md:
--------------------------------------------------------------------------------
1 | # Introducing the Botkit Message Pipeline
2 |
3 | As Botkit has added support for more and more new platforms,
4 | it has become necessary to formalize the process by which
5 | incoming messages are received and prepared for use within
6 | the bot's brain, and also how outgoing messages are formatted
7 | and delivered to the appropriate messaging platform APIs.
8 |
9 | The new message pipeline introduced in Botkit 0.6 defines this
10 | formal path by exposing a series of middleware endpoints that occur
11 | throughout the lifetime of a message as it is is transformed
12 | from a "raw" message received from the platform into its normalized
13 | form. This normalization process allows Botkit and its array of plugins to handle a message without necessarily caring about its origin.
14 |
15 | Message normalization like this has always been part of Botkit -
16 | what is being introduced in 0.6 is a formalized process through which
17 | all messages must now flow.
18 |
19 | This document should be useful to any developer interested in using Botkit's middleware system. However, the focus of this document is on the application of the available middleware endpoints to the process of message normalization in platform connectors. Developers interested in using middleware for building plugins or for feature development should [check out the main middleware documentation](middleware.md).
20 |
21 | ## Why do we need a message pipeline?
22 |
23 | Each messaging service that works with Botkit sends messages in a different format - some even come in multiple formats! Some of the services send messages via incoming webhook, while others send them via web sockets. Some require decryption or other processing before being used by the bot. This means that
24 | each different type of bot has to treat the messages differently, depending on all these factors.
25 |
26 | The message pipeline is a series of steps that Botkit takes for every single message that tries to manage all this chaos. It is a universal process that is applied to all messages from all platforms that results in a simple normalized message format.
27 |
28 | We hope that this will simplify the process of learning to use Botkit,
29 | increase the ability of developers to port their bots between platforms or
30 | build multi-platform bot apps, and make it easier for plugin developers to
31 | create extensions to Botkit that work seamlessly with all messaging services.
32 |
33 | ## How does it work?
34 |
35 | Messages that arrive to a Botkit-powered app are now passed into the message
36 | processing pipeline via a function called `ingest()` that receives the raw,
37 | unprocessed payload of the incoming message - a big blob of information in some platform specific format.
38 |
39 | Somewhere in that blob of information are a few key pieces of information that Botkit really cares about and needs to know about to work: the text, the user, the channel, and the type of the message.
40 |
41 | Once ingested, Botkit passes the message through a series of transformations,
42 | each one with its own middleware plugin endpoint. The result of these transformations is a message object that is guaranteed to have all of those bits of information in the right places. This transformed message is then passed into Botkit to be handled by your application.
43 |
44 | As a result, developers writing normal Botkit code can always expect a message to be in the form:
45 |
46 | ```
47 | {
48 | user: ,
49 | channel: ,
50 | text: ,
51 | type: ,
52 | raw_message:
53 | }
54 | ```
55 |
56 | The same process is reversed when sending a message. Developers can author messages in a generic form, in many cases only specifying the outgoing text.
57 | These messages are then transformed by the outgoing message pipeline into
58 | the platform-specific API payloads necessary.
59 |
60 | ### Incoming Messages
61 |
62 | The incoming message pipeline consists of these steps:
63 |
64 | * [Ingest](#ingest) - receive a raw incoming message event
65 | * [Normalize](#normalize) - copy, rename or transform fields in the message so that it matches Botkit's expectations
66 | * [Categorize](#categorize) - adjust the type of the message depending on its content. for example, identifying the difference between a direct message and a direct mention.
67 | * [Receive](#receive) - accepts the normalized and transformed message for processing
68 |
69 | After passing through the `receive` step, one of three things will happen:
70 |
71 | * the message is recognized as part of an ongoing conversation, and captured by that conversation. This will fire the [capture middleware](#capture) .
72 | * the message matches a 'hears' pattern and passed in to a handler function. This will fire the [heard middleware](#heard) .
73 | * the message will trigger a Botkit event based on value of the `message.type` field. No further middleware will fire in this case.
74 |
75 | ### Outgoing Messages
76 |
77 | The outgoing message pipeline consists of these steps:
78 |
79 | * [Send](#send) - accept an outgoing message to be sent to a message platform.
80 | * [Format](#format) - do the necessary transformations from a simplified Botkit message object to the platform specific API payload
81 |
82 | # Middleware Definitions
83 |
84 | The pipeline middlewares are useful for two primary reasons:
85 |
86 | * It allows the development of new platform connectors via a prescribed mechanism
87 | * It gives developers hooks to modify the internal workings of Botkit
88 |
89 | Middleware functions can be developed to do all sorts of useful things, and can now be tied the pipeline at any phase, depending on the purpose of the middleware.
90 |
91 | As of version 0.6, all Botkit platform connectors include middleware functions
92 | responsible for their platform-specific transformations. These platform middlewares will _always fire first_, before any additional middlewares defined by the developer or included in the application code.
93 |
94 | Developers can specify as many middlewares as desired, including multiple middleware functions registered to the same endpoints. These functions will fire in the order they are defined.
95 |
96 | Plugin middlewares can do things like:
97 | * Call third party NLP/NLU APIs and enrich the message object
98 | * Load information from databases and enrich the message object
99 | * Verify or authenticate message objects and discard unverified or unwanted messages
100 | * Further categorize messages in order to fire new or different events
101 | * Handle classes of events "in the background" without changing specific handlers
102 | * Log or record messages for debugging or statistics
103 |
104 |
105 | ## Ingest
106 |
107 | Ingestion into Botkit is the first step in the message pipeline.
108 |
109 | Message objects that pass through the ingest phase will have 2 additional fields:
110 |
111 | `message.raw_message` contains the unmodified content of the incoming message payload as received from the messaging service
112 |
113 | `message._pipeline` is an object that tracks a message's progress through the pipeline. The subfield `message._pipeline.stage` will contain the name of the current pipeline step.
114 |
115 | Functions added to the ingest middleware endpoint need to receive 4 parameters, as below.
116 |
117 | | Field | Description
118 | |--- |---
119 | | bot | an instance of the bot
120 | | message | the incoming message object
121 | | response channel | the http response object
122 | | next | function to call to proceed with pipeline
123 |
124 |
125 | ```
126 | controller.middleware.ingest.use(function(bot, message, res, next) {
127 |
128 | // define action
129 | // perhaps set an http status header
130 | // res.status(200);
131 | // you can even send an http response
132 | // res.send('OK');
133 |
134 | // you can access message.raw_message here
135 |
136 | // call next to proceed
137 | next();
138 |
139 | });
140 | ```
141 |
142 | The ingest phase is useful for actions like:
143 |
144 | * Validating the origin of the incoming payload using a shared secret or encrypted header
145 | * Sending necessary HTTP response to the incoming webhooks. For example, some platforms require a 200 response code!
146 |
147 | Note that in the ingest phase, the message object has _not yet been normalized_ and may not contain the fields you expect. Developers should treat these messages as raw, platform specific messages,
148 | and as a result should check the `bot.type` field, which contains the name of the specific messaging platform, before taking any actions on the message object!
149 |
150 | ## Normalize
151 |
152 | Normalization is the second phase of the message pipeline.
153 |
154 | After passing through the normalize phase, the message object is expected to have the following fields:
155 |
156 | * `type` will contain either the raw value of the incoming `type` field specified by the platform, OR `message_received` which is the default message type defined by Botkit.
157 | * `user` will contain the unique id of the sending user
158 | * `channel` will include the unique id of the channel in which the message was sent
159 | * `text` will contain the text, if any, of the message.
160 |
161 | Note that the entire original unmodified message object will still be available as `message.raw_message`. Though Botkit's normalization process does not remove any fields from the message as it is normalized, those fields are not guaranteed to be present. It is our recommendation that developers who want to access to platform-specific fields _always_ use the `message.raw_message` location.
162 |
163 | For example, if the originally ingested payload included a field called `message.my_platform_value`, you should refer to it in your code as `message.raw_message.my_platform_value`.
164 |
165 | Functions added to the normalize middleware endpoint need to receive these parameters:
166 |
167 | | Field | Description
168 | |--- |---
169 | | bot | an instance of the bot
170 | | message | the incoming message object
171 | | next | function to call to proceed with pipeline
172 |
173 | ```
174 | controller.middleware.normalize.use(function(bot, message, next) {
175 |
176 | // here's an example of what a message normalizer might do!
177 | // this is a make believe example not specific to any real platform
178 | // the idea is to copy/rename or tranform fields from raw_message
179 | // into an object with {user, text, channel, type} while leaving everything else alone
180 |
181 | // translate a "from" field into message.user
182 | message.user = message.raw_message.from.id;
183 |
184 | // find the text value and set it in message.text
185 | message.text = message.raw_message.user_text;
186 |
187 | // make sure a channel value is set
188 | message.channel = message.raw_message.source_channel
189 |
190 | // call next to proceed
191 | next();
192 |
193 | });
194 | ```
195 |
196 |
197 | ## Categorize
198 |
199 | Categorization is the third phase of the message pipeline.
200 |
201 | After passing through the catgorize phase, the message object's `type` field
202 | should represent a the final event type that will be handled by Botkit.
203 |
204 | The most obvious example of a categorization action is identifying and transforming a message from a generic `message_received` event into more narrowly defined `direct_message`, `direct_mention`, `mention` or `ambient` message event.
205 |
206 | In addition to changing the message `type` field, the `categorize` middleware may also
207 | change the value of the `message.text` field. For example, it should _remove direct mentions from the text_ so that developers do not have to compensate for its possible presence in the input text.
208 |
209 | Categorize middlewares can also catch and delegate complex message types to simpler,
210 | easier to handle events, taking some of the burden off of developers for handling these subtleties. For example, a categorize middleware might identify different types of button click events that all share the same `type` value and create new event names for each.
211 |
212 | Functions added to the categorize middleware endpoint need to receive these parameters:
213 |
214 | | Field | Description
215 | |--- |---
216 | | bot | an instance of the bot
217 | | message | the incoming message object
218 | | next | function to call to proceed with pipeline
219 |
220 | ```
221 | controller.middleware.categorize.use(function(bot, message, next) {
222 |
223 | // messages in Slack that are sent in a 1:1 channel
224 | // can be identified by the first letter of the channel ID
225 | // if it is "D", this is a direct_message!
226 | if (message.type == 'message_received') {
227 | if (message.channel[0] == 'D') {
228 | message.type = 'direct_message';
229 | }
230 | }
231 |
232 | // call next to proceed
233 | next();
234 |
235 | });
236 | ```
237 |
238 |
239 | ## Receive
240 |
241 | Receive is the final step in the incoming message pipeline before the message
242 | actually reaches the bot's internal logic.
243 |
244 | By the time a message hits the `receive` stage, it is in its final form,
245 | and is ready to be processed by a Botkit event handler. This middleware endpoint
246 | occurs _just before_ a message is evaluated for trigger matches, and before any
247 | user-defined handler runs. It will fire for every incoming message, regardless of whether or not it matches a trigger or if any event handlers are registered to receive it.
248 |
249 | As noted above, after passing through the `receive` step, one of three things will happen:
250 |
251 | * the message is recognized as part of an ongoing conversation, and captured by that conversation. This will fire the [capture middleware](#capture) .
252 | * the message matches a 'hears' pattern and passed in to a handler function. This will fire the [heard middleware](#heard) .
253 | * the message will trigger a Botkit event based on value of the `message.type` field. No further middleware will fire in this case, and Botkit will fire any handlers registered with the `controller.on()` function.
254 |
255 | Developers seeking to enrich their messages with data from external sources, such as external NLP services, databases or other third party APIs, may wish to tie this functionality to the receive middleware endpoint. This will cause the enrichment to occur for _every single message_ that is received. This may or may not be desirable, depending on the number and type of messages the platforms send, and the types of messages your bot is supposed to handle.
256 |
257 | Before calling any external service in a receive middleware, developers should evaluate the message's `type` and `text` field to make sure enrichment is appropriate. For example, you don't want to call an expensive NLP process on messages without text, or messages that represent button clicks.
258 |
259 | Alternately, developers may wish to attach their enrichment functionality to the more narrowly defined `heard` and `capture` middlewares, which occur _after_ pattern matching has occured, and as a result will only fire for messages that _are definitely going to be handled_.
260 |
261 | Functions added to the categorize middleware endpoint need to receive these parameters:
262 |
263 | | Field | Description
264 | |--- |---
265 | | bot | an instance of the bot
266 | | message | the incoming message object
267 | | next | function to call to proceed with pipeline
268 |
269 | ```
270 | controller.middleware.receive.use(function(bot, message, next) {
271 |
272 | // lets call a pretend external NLP system
273 | // and enrich this message with intent and entity data
274 |
275 | // make sure we have some text, and that this is
276 | // not a message from the bot itself...
277 | if (message.text && message.type != 'self_message') {
278 | callExternalNLP(message.text).then(function(api_results) {
279 | message.intent = api_results.intent;
280 | message.entities = api_results.entities;
281 | next();
282 | });
283 | } else {
284 | next();
285 | }
286 | });
287 | ```
288 |
289 | ## Heard
290 |
291 | The `heard` middleware endpoint occurs after a message has matched a trigger pattern, and is about to be handled. It works just like the `receive` endpoint, but instead of firing for every incoming message, it will only fire for messages that the is explicitly listening for.
292 |
293 | This makes the `heard` endpoint useful for firing expensive operations, such as database lookups or calls to external APIs tat take a long time, require a lot of processing, or actually cost money to use. However, it makes it less useful for use with NLP tools, since the pattern matching has already occured.
294 |
295 | Note that the heard middleware fires only for messages that match handlers set up with `controller.hears()`, and does not fire with handlers configured with the `controller.on()` method.
296 |
297 | Functions added to the categorize heard endpoint need to receive these parameters:
298 |
299 | | Field | Description
300 | |--- |---
301 | | bot | an instance of the bot
302 | | message | the incoming message object
303 | | next | function to call to proceed with pipeline
304 |
305 | ```
306 | controller.middleware.heard.use(function(bot, message, next) {
307 |
308 | // load up any user info associated with this sender
309 | // using Botkit's internal storage system
310 | // and enrich the message with a new `user_profile` field
311 | // now, every message will have the user_profile field automatically
312 | // and you don't need to load the info in each individual handler function
313 | controller.storage.users.get(message.user, function(err, user_profile) {
314 | if (!err && user_profile) {
315 | message.user_profile = user_profile;
316 | }
317 |
318 | // call next to proceed, now with additional info!
319 | next();
320 | });
321 | });
322 | ```
323 |
324 | ## Capture
325 |
326 | The `capture` middleware once again works like the `receive` or `heard` endpoints,
327 | but fires only on the condition that the incoming message is part of an existing
328 | conversation. Generally, this means that the message will actually be handled a callback function passed into `convo.ask()`
329 |
330 | This endpoint is useful for transforming the value used by the conversation to something
331 | other than the user's raw input text. For example, in a bot that presents a numbered list of options to a user as part of a multiple choice selection, a capture middleware could be created that transforms the user's numeric input into the full text of the selected item.
332 |
333 |
334 | ## Send
335 |
336 | When you send a message with `bot.send()` or `bot.reply()`, the outgoing message is first sent
337 | through the send middleware.
338 |
339 | The send middleware receives the raw message, as created in your bot's code. It has not yet been formatted for delivery to the messaging service API. This can be used to modify or track the outgoing messages BEFORE they are formatted for delivery to the platform API.
340 |
341 | In particular, this middleware is useful for recording stats about outgoing messages. At this point in the pipeline, the message object will contain the outgoing message text and any attachments, as well as a special `message.to` field, which represents the unique user id of the message's recipient. Depending on the platform, this value is not always present in the final outgoing message payload.
342 |
343 | Any modifications to the _content_ of the outgoing message should happen in a send middleware function. For example, developers can use a send middleware to translate the message text into different languages. Or, developers might pass the message text through a template engine to replace tokens or expand custom shortcodes.
344 |
345 | Send middlewares should _not_ make changes to the actual structure or layout of the outgoing message object. Final formatting for delivery to the platform is done by the `format` endpoint.
346 |
347 | Functions added to the categorize send endpoint need to receive these parameters:
348 |
349 | | Field | Description
350 | |--- |---
351 | | bot | an instance of the bot
352 | | message | the outgoing message object
353 | | next | function to call to proceed with pipeline
354 |
355 | ```
356 | controller.middleware.send.use(function(bot, message, next) {
357 |
358 | // log the outgoing message for debugging purposes
359 | console.log('SENDING ', message.text,'TO USER', message.text);
360 |
361 | next();
362 |
363 | });
364 | ```
365 |
366 | ## Format
367 |
368 | This middleware happens immediately before a message is delivered to the platform API.
369 |
370 | Each platform as its own special format for incoming message objects. This middleware should exclusively be used for constructing the final API parameters required for delivering the message. The message object that emerges from this function is intended only for use with the messaging service API.
371 |
372 | After being formatted, the resulting `platform_message` is passed into the platform-specific `bot.send()` function, which is responsible for the final delivery of the message the appropriate external API endpoint. This allows the `bot.send()` function to be designed to accept only pre-formatted messages.
373 |
374 | Unlike all the other pipeline endpoints, this function does NOT modify the original message object. In fact, the final object is constructed by the middleware in the `platform_message` parameter,
375 | allowing the original message to pass through unmolested.
376 |
377 | Functions added to the categorize format endpoint need to receive these parameters:
378 |
379 | | Field | Description
380 | |--- |---
381 | | bot | an instance of the bot
382 | | message | the outgoing message object
383 | | platform_message | the formatted message, ready for delivery
384 | | next | function to call to proceed with pipeline
385 |
386 | ```
387 | controller.middleware.format.use(function(bot, message, platform_message, next) {
388 |
389 | // let's construct an outgoign message payload
390 | // to an imaginary platform that uses some different fieldnames.
391 |
392 | platform_message.message = {
393 | text: message.text,
394 | recipient: message.to,
395 | room: message.channel,
396 | }
397 |
398 | platform_message.type = 'message';
399 |
400 | next();
401 |
402 | });
403 | ```
404 |
--------------------------------------------------------------------------------
/docs/readme-studio.md:
--------------------------------------------------------------------------------
1 | # Building with Botkit Studio
2 |
3 | **Please note: Botkit Studio will cease operation on Feb 14, 2019. The features below are now available through [Botkit CMS](https://github.com/howdyai/botkit-cms)**
4 |
5 | [Botkit Studio](https://studio.botkit.ai) was a hosted development tool that enhances and expands the capabilities of Botkit. While developers may use Botkit without Studio, a Studio account will substantially ease the development and deployment of a Bot, help to avoid common coding pitfalls,
6 | a valuable management interface for the bot's dialog content and configuration. Botkit Studio is a product of [Howdy.ai](http://howdy.ai), the creators of Botkit.
7 |
8 | This document covers the Botkit Studio SDK details only. [Start here](core.md) if you want to learn about to develop with Botkit.
9 |
10 | For bot developers who have existing apps but would like to benefit from features like bot-specific content management without using Botkit, you can access the [Botkit Studio SDK here](https://github.com/howdyai/botkit-studio-sdk)
11 |
12 | Table of Contents
13 |
14 | * [Key Features](#key-features)
15 | * [Getting Started](#getting-started)
16 | * [Function Index](#function-index)
17 |
18 | ## Key Features
19 | ### Why use Botkit Studio?
20 | The goal of Botkit Studio is to make building bots with Botkit easier than ever before.
21 | The tools and this SDK are based on feedback from dozens of Botkit developers and more than a year of building and operating our flagship bot, [Howdy](https://howdy.ai).
22 | However, our intent is not to cover every base needed for building a successful bot. Rather, we focus on several key problem areas:
23 |
24 | * **Script Authoring**: Botkit Studio provides a cloud-based authoring tool for creating and maintaining multi-thread conversations and scripts. Scripts managed in Studio can be changed without changing the underlying application code, allowing for content updates, feature additions and product development without code deploys. Many types of conversation will _no longer require code_ to function.
25 |
26 | * **Trigger Management**: Developers may define trigger words and patterns externally from their code, allowing those triggers to expand and adapt as humans use the bot.
27 |
28 | * **Easy to use SDK**: Our open source SDK provides simple mechanisms for accessing these features from within your application. With only a few new functions: [studio.get](#controllerstudioget), [studio.run](#controllerstudiorun), and [studio.runTrigger](#controllerruntrigger), your bot has full access to all of the content managed by the cloud service. These functions can be used to build light weight integrations with Studio, or turn over complete control to the cloud brain.
29 |
30 | 
31 |
32 | The screenshot above shows the script authoring tool, where bot developers can write dialog,
33 | manage [conversation threads](core.md#conversation-threads), define variables to capture user input, and set triggers that will automatically activate the bot.
34 |
35 | ## Getting Started
36 |
37 | Before you get started, it is important to note that Botkit Studio is an extra set of features
38 | built on top of [all of the other existing Botkit features and plugins](core.md), and all of the documentation and tutorials for those features applies to bots built with Studio as well.
39 |
40 | If you already have a Botkit bot, you may want to start [here](#adding-studio-features-to-an-existing-bot).
41 |
42 | The instructions below cover setting up a bot on a Slack team. However, you may also use any of the other Botkit connectors to operate a bot on [Facebook](readme-facebook.md), [Twilio](readme-twilioipm.md), or any other supported platform. Follow the instructions for configuring Botkit on those dedicated pages, then pick up below with the additional Studio configuration steps.
43 |
44 | ### Start with the Starter Kit
45 |
46 | 1) [Register for a developer account at Botkit Studio](https://studio.botkit.ai/signup)
47 |
48 | 2) Download the Botkit Studio Starter Kit [for Slack](https://github.com/howdyai/botkit-starter-slack) or [for Facebook Messenger](https://github.com/howdyai/botkit-starter-facebook). This code repository contains a fully functioning bot configured to work with Botkit Studio, and code examples demonstrating all of the key features. It also contains supporting material for the [tutorial included here](#tutorial).
49 |
50 | 3) Make a bot integration inside of your Slack channel. Go here:
51 |
52 | https://my.slack.com/services/new/bot
53 |
54 | Enter a name for your bot.
55 | Make it something fun and friendly, but avoid a single task specific name.
56 | Bots can do lots! Let's not pigeonhole them.
57 |
58 | When you click "Add Bot Integration", you are taken to a page where you can add additional details about your bot, like an avatar, as well as customize its name & description.
59 |
60 | Copy the API token that Slack gives you. You'll need it.
61 |
62 | 4) Inside Botkit Studio, locate the "API Keys" tab for your bot account, and copy the token. Now you've got everything you need!
63 |
64 | 4) With both tokens in hand, run the starter kit bot application from your command line:
65 |
66 | ```
67 | token=REPLACE_THIS_WITH_YOUR_TOKEN studio_token=REPLACE_WITH_YOUR_BOTKIT_TOKEN node .
68 | ```
69 |
70 | 5) Your bot should be online! Within Slack, send it a quick direct message to say hello. It should say hello back!
71 |
72 | 6) Create new scripts, triggers and behaviors within your Botkit Studio developer account, while connecting it to the application logic present in your bot code by using the features described [in the function index](#function-index).
73 |
74 | ### Adding Studio Features to an Existing Bot
75 |
76 | If you've already got a bot built with Botkit, you can get started with new Studio features with only a few extra lines of code.
77 |
78 | After you've registered for a Botkit Studio developer account, you will receive an API token that grants your bot access to the content and features managed by the Studio cloud service. You can add this to your existing Botkit app by passing in the Studio token to the Botkit constructor using the `studio_token` field:
79 |
80 | ```javascript
81 | // Create the Botkit controller that has access to Botkit Studio
82 | var controller = Botkit.slackbot({
83 | debug: false,
84 | studio_token: 'MY_BOTKIT_STUDIO_TOKEN'
85 | });
86 | ```
87 |
88 | In order to add the Botkit Studio "catch all" handler that will activate the cloud script triggering service into your bot, add the following code to your application below all other Botkit `hears()` events. This will pass any un-handled direct message or direct mention through Botkit Studio's trigger service, and, should a matching trigger be found, execute the script.
89 |
90 | ```javascript
91 | controller.on('direct_message,direct_mention,mention', function(bot, message) {
92 | controller.studio.runTrigger(bot, message.text, message.user, message.channel).catch(function(err) {
93 | bot.reply(message, 'I experienced an error with a request to Botkit Studio: ' + err);
94 | });
95 | });
96 | ```
97 |
98 | ## The Botkit Studio Data Flow
99 | ### Keep your bot secure and your user messages private!
100 |
101 | How do the Botkit tools handle your messages? Where do messages come from and go to?
102 |
103 | 1. The Botkit-powered application you build (and host yourself) receives messages directly from a messaging platform such as Slack or Facebook.
104 |
105 | 2. Botkit will evaluate this message locally (within your application) to match it to internally defined triggers (using `hears()` or `on()` handlers).
106 |
107 | 3. If and only if a message matches the conditions for being analyzed remotely -- by default, only messages sent directly to the bot that are not already part of an ongoing interaction -- the message is sent over an encrypted SSL channel to the Botkit Studio trigger system.
108 |
109 | The trigger system (using [studio.runTrigger](#controllerstudioruntrigger)) will evaluate the input message against all configured triggers, and, should one be matched, return the full content of the script to your application.
110 |
111 | 4. Botkit will _compile_ the script received from the API into a [conversation object](core.md#multi-message-replies-to-incoming-messages) and conduct the resulting conversation. During the course of the conversation, *no messages* are sent to the Botkit Studio APIs. Said another way, while a bot is conducting a scripted conversation, all messages are sent and received directly between the application and the messaging platform. This projects your user's messages, reduces network traffic, and ensures that your bot will not share information unnecessarily.
112 |
113 | Our recommended best practices for the security and performance of your bot and the privacy of your users is to send as few messages to be interpreted by the trigger APIs as possible. As described above, a normal Botkit Studio bot should _only_ send messages to the API that can reasonably be expected to contain trigger words.
114 |
115 | The bottom line is, Botkit Studio does _not_ put itself between your users and your application. All messages are delivered _first_ and directly to your application, and only sent to our APIs once specific criteria are met. This is notably different than some other bot building services that actually receive and process messages on your behalf.
116 |
117 | ## Function Index
118 |
119 | #### controller.studio.run()
120 | | Argument | Description
121 | |--- |---
122 | | bot | A bot instance
123 | | input_text | The name of a script defined in Botkit Studio
124 | | user | the user id of the user having the conversation
125 | | channel | the channel id where the conversation is occurring
126 |
127 | `controller.studio.run()` will load a script defined in the Botkit Studio authoring tool, convert it into a Botkit conversation, and perform the conversation to it's completion.
128 |
129 | Developers may tap into the conversation as it is conducted using the [before](#controllerstudiobefore), [after](#controllerstudioafter), and [validate](#controllerstudiovalidate) hooks. It is also possible to bind to the normal `convo.on('end')` event because this function also returns the resulting conversation object via a promise:
130 |
131 | ```javascript
132 | controller.studio.run(bot, 'hello', message.user, message.channel).then(function(convo) {
133 | convo.on('end', function(convo) {
134 | if (convo.status=='completed') {
135 | // handle successful conversation
136 | } else {
137 | // handle failed conversation
138 | }
139 | });
140 | });
141 | ```
142 |
143 | #### controller.studio.get()
144 | | Argument | Description
145 | |--- |---
146 | | bot | A bot instance
147 | | input_text | The name of a script defined in Botkit Studio
148 | | user | the user id of the user having the conversation
149 | | channel | the channel id where the conversation is occurring
150 |
151 | `controller.studio.get()` is nearly identical to `controller.studio.run()`, except that instead of automatically and immediately starting the conversation, the function returns it in a dormant state.
152 |
153 | While developers may still tap into the conversation as it is conducted using the [before](#controllerstudiobefore), [after](#controllerstudioafter), and [validate](#controllerstudiovalidate) hooks, it must first be activated using `convo.activate()` in the results of the promise returned by the function.
154 |
155 | This enables developers to add template variables to the conversation object before it sends its first message. Read about [using variables in messages](core.md#using-variable-tokens-and-templates-in-conversation-threads)
156 |
157 | ```javascript
158 | controller.studio.get(bot, 'hello', message.user, message.channel).then(function(convo) {
159 | convo.setVar('date', new Date()); // available in message text as {{vars.date}}
160 | convo.setVar('news', 'This is a news item!'); // ailable as {{vars.news}}
161 |
162 | // crucial! call convo.activate to set it in motion
163 | convo.activate();
164 | });
165 | ```
166 |
167 |
168 | #### controller.studio.getById()
169 | | Argument | Description
170 | |--- |---
171 | | bot | A bot instance
172 | | id | The id of a script defined in Botkit Studio
173 | | user | the user id of the user having the conversation
174 | | channel | the channel id where the conversation is occurring
175 |
176 | `controller.studio.getById()` returns a script identified by its ID rather than name. Otherwise it works in the same manner as `controller.studio.get()`
177 |
178 |
179 | #### controller.studio.runTrigger()
180 | | Argument | Description
181 | |--- |---
182 | | bot | A bot instance
183 | | input_text | The name of a script defined in Botkit Studio
184 | | user | the user id of the user having the conversation
185 | | channel | the channel id where the conversation is occurring
186 |
187 | In addition to storing the content and structure of conversation threads, developers can also use Botkit Studio to define and maintain the trigger phrases and patterns that cause the bot to take actions. `controller.studio.runTrigger()` takes _arbitrary input text_ and evaluates it against all existing triggers configured in a bot's account. If a trigger is matched, the script data is returned, compiled, and executed by the bot.
188 |
189 | This is different than `studio.run()` and `studio.get()` in that the input text may include _additional text_ other than an the exact name of a script. In most cases, `runTrigger()` will be configured to receive all messages addressed to the bot that were not otherwise handled, allowing Botkit Studio to be catch-all. See below:
190 |
191 | ```javascript
192 | // set up a catch-all handler that will send all messages directed to the bot
193 | // through Botkit Studio's trigger evaluation system
194 | controller.on('direct_message,direct_mention,mention', function(bot, message) {
195 | controller.studio.runTrigger(bot, message.text, message.user, message.channel).catch(function(err) {
196 | bot.reply(message, 'I experienced an error with a request to Botkit Studio: ' + err);
197 | });
198 | });
199 | ```
200 |
201 | In order to customize the behavior of scripts triggered using `runTrigger()`, developers define `before`, `after` and `validate` hooks for each script. See docs for these functions below.
202 |
203 | Another potential scenario for using `runTrigger()` would be to trigger a script that includes additional parameters that would normally be provided by a user, but are being provided instead by the bot. For example, it is sometimes useful to trigger another script to start when another script has ended.
204 |
205 | ```javascript
206 | controller.hears(['checkin'], 'direct_message', function(bot, message) {
207 |
208 | // when a user says checkin, we're going to pass in a more complex command to be evaluated
209 |
210 | // send off a string to be evaluated for triggers
211 | // assuming a trigger is setup to respond to `run`, this will work!
212 | controller.studio.runTrigger(bot, 'run checkin with ' + message.user, message.user, message.channel);
213 | });
214 | ```
215 |
216 | ### A note about handling parameters to a trigger
217 |
218 | While Botkit does not currently provide any built-in mechanisms for extracting entities or parameters from the input text, that input text remains available in the `before` and `after` hooks, and can be used by developers to process this information.
219 |
220 | The original user input text is available in the field `convo.source_message.text`. An example of its use can be see in the [Botkit Studio Starter bot](https://github.com/howdyai/botkit-studio-starter), which extracts a parameter from the help command.
221 |
222 | ```javascript
223 | controller.studio.before('help', function(convo, next) {
224 |
225 | // is there a parameter on the help command?
226 | // if so, change topic.
227 | if (matches = convo.source_message.text.match(/^help (.*)/i)) {
228 | if (convo.hasThread(matches[1])) {
229 | convo.gotoThread(matches[1]);
230 | }
231 | }
232 |
233 | next();
234 |
235 | });
236 | ```
237 |
238 |
239 | #### controller.studio.getScripts()
240 | | Argument | Description
241 | |--- |---
242 | | bot | A bot instance (required only when Botkit Studio token is associated with bot, not controller)
243 | | tag | (optional) require that all scripts returned have specified tag
244 |
245 | This function will return a list of all Botkit Studio scripts available to the bot.
246 | It returns a promise that will resolve with an array of scripts. These scripts will contain
247 | the `name`, `description`, and a list of associated `triggers`. The `name` field can be used
248 | along with `controller.studio.get()` and `controller.studio.run()` to load the actual content of the script.
249 |
250 | ```javascript
251 | controller.studio.getScripts().then(function(list) {
252 |
253 | // do something with this array of scripts.
254 | // list an array in the form:
255 | // [
256 | // {
257 | // name: 'script',
258 | // description: 'a script',
259 | // triggers: [
260 | // type: 'string',
261 | // pattern: 'trigger',
262 | // ]
263 | // }
264 | // ]
265 |
266 | });
267 | ```
268 |
269 |
270 |
271 | #### controller.studio.before()
272 | | Argument | Description
273 | |--- |---
274 | | script_name | The name of a script defined in Botkit Studio
275 | | hook_function | A function that accepts (convo, next) as parameters
276 |
277 | Define `before` hooks to add data or modify the behavior of a Botkit Studio script _before_ it is activated. Multiple before hooks can be defined for any script - they will be executed in the order they are defined.
278 |
279 | Note: hook functions _must_ call next() before ending, or the script will stop executing and the bot will be confused!
280 |
281 | ```javascript
282 | // Before the "tacos" script runs, set some extra template tokens like "special" and "extras"
283 | controller.studio.before('tacos', function(convo, next) {
284 |
285 | convo.setVar('special', 'Taco Boats');
286 | convo.setVar('extras', [{'name': 'Cheese'}, {'name': 'Lettuce'}]);
287 |
288 | next();
289 |
290 | });
291 | ```
292 |
293 |
294 | #### controller.studio.after()
295 | | Argument | Description
296 | |--- |---
297 | | script_name | The name of a script defined in Botkit Studio
298 | | hook_function | A function that accepts (convo, next) as parameters
299 |
300 | Define `after` hooks capture the results, or take action _after_ a Botkit Studio script has finished executing. Multiple after hooks can be defined for any script - they will be executed in the order they are defined.
301 |
302 | Note: hook functions _must_ call next() before ending, or the script will stop executing and the bot will be confused!
303 |
304 | ```javascript
305 | // After the "tacos" command is finished, collect the order data
306 | controller.studio.after('tacos', function(convo, next) {
307 | if (convo.status == 'completed') {
308 | var responses = convo.extractResponses();
309 | // store in a database
310 | }
311 | next();
312 | });
313 | ```
314 |
315 |
316 | #### controller.studio.validate()
317 | | Argument | Description
318 | |--- |---
319 | | script_name | The name of a script defined in Botkit Studio
320 | | variable_name | The name of a variable defined in Botkit Studio
321 | | hook_function | A function that accepts (convo, next) as parameters
322 |
323 | `validate` hooks are called whenever a Botkit Studio script sets or changes the value of a variable that has been defined as part of the script.
324 |
325 | Note: hook functions _must_ call next() before ending, or the script will stop executing and the bot will be confused!
326 |
327 | ```javascript
328 | // Validate a "sauce" variable in the "taco" script
329 | // this will run whenever the sauce variable is set and can be used to
330 | // alter the course of the conversation
331 | controller.studio.validate('tacos', 'sauce', function(convo, next) {
332 |
333 | var sauce = convo.extractResponse('sauce');
334 | sauce = sauce.toLowerCase();
335 |
336 | if (sauce == 'red' || sauce == 'green' || sauce == 'cheese') {
337 | convo.setVar('valid_sauce', true);
338 | next();
339 | } else {
340 | convo.gotoThread('wrong_sauce');
341 | next();
342 | }
343 |
344 | });
345 | ```
346 |
347 | #### controller.studio.beforeThread()
348 | | Argument | Description
349 | |--- |---
350 | | script_name | The name of a script defined in Botkit Studio
351 | | thread_name | The name of a thread defined in Botkit Studio
352 | | hook_function | A function that accepts (convo, next) as parameters
353 |
354 | `beforeThread` hooks are called whenever a Botkit Studio script changes from one thread to another.
355 |
356 | This works just like [convo.beforeThread()](core.md#convobeforethread), but operates on the automagically compiled scripts managed by Botkit Studio's IDE.
357 |
358 | Note: hook functions _must_ call next() before ending, or the script will stop executing and the bot will be confused!
359 | Allows developers to specify one or more functions that will be called before the thread
360 | referenced in `thread_name` is activated.
361 |
362 | `handler_function` will receive the conversation object and a `next()` function. Developers
363 | must call the `next()` function when their asynchronous operations are completed, or the conversation
364 | may not continue as expected.
365 |
366 | Note that if `gotoThread()` is called inside the handler function,
367 | it is recommended that `next()` be passed with an error parameter to stop processing of any additional thread handler functions that may be defined - that is, call `next('stop');`
368 |
369 | ```javascript
370 | // This example demonstrates how to use beforeThread to capture user input, do an asynchronous operation, then display the results in a new thread
371 | // Imagine a conversation called `search` in which the first action is to collect search terms
372 | // the conversation then transitions to the `results` thread, before which we do the actual search!
373 | controller.studio.beforeThread('search', 'results', function(convo, next) {
374 |
375 | var query = convo.extractResponse('query');
376 | mySearchQuery(query).then(function(results) {
377 |
378 | convo.setVar('results', results);
379 | next();
380 |
381 | }).catch(function(err) {
382 |
383 | convo.setVar('error', err);
384 | convo.gotoThread('error');
385 | next(err);
386 |
387 | });
388 |
389 | });
390 | ```
391 |
--------------------------------------------------------------------------------
/docs/readme-twilioipm.md:
--------------------------------------------------------------------------------
1 | # Botkit and Twilio IP Messaging
2 |
3 | Table of Contents
4 |
5 | * [Getting Started](#getting-started)
6 | * [Twilio IPM Events](#twilio-ipm-specific-events)
7 | * [Working with Twilio IPM](#working-with-twilio-ip-messaging)
8 | * [System Bots vs User Bots](#system-bots-vs-user-bots)
9 | * [Using Twilio's API](#using-the-twilio-api)
10 |
11 | ## Getting Started
12 |
13 | 1) Install Botkit [more info here](core.md#installation)
14 |
15 | 2) Register a developer account with Twilio. Once you've got it, navigate your way to the [Get Started with IP Messaging](https://www.twilio.com/user/account/ip-messaging/getting-started) documentation on Twilio's site. Read up!!
16 |
17 | 3) To get your bot running, you need to collect *5 different API credentials*. You will need to acquire your Twilio Account SID, Auth Token, Service SID, API Key, and your API Secret to integrate with your Botkit. This is a multi-step process!
18 |
19 | ##### Twilio Account SID and Auth Token
20 |
21 | These values are available on your [Twilio Account page](https://www.twilio.com/user/account/settings). Copy both the SID and token values.
22 |
23 | ##### API Key and API Secret
24 |
25 | To get an API key and secret [go here](https://www.twilio.com/user/account/ip-messaging/dev-tools/api-keys) and click 'Create an API Key'. Provide a friendly name for the API service and click 'Create API Key'. Be sure to copy your Twilio API key and API Secret keys to a safe location - this is the last time Twilio will show you your secret! Click the checkbox for 'Got it! I have saved my API Key Sid and Secret in a safe place to use in my application.'
26 |
27 | ##### Service SID
28 |
29 | To generate a Twilio service SID, [go here](https://www.twilio.com/user/account/ip-messaging/services) and click 'Create an IP Messaging Service'.
30 |
31 | Provide a friendly name and click 'create'. At the top under 'Properties' you should see Service SID. Copy this to a safe place. You now have all 5 values!
32 |
33 | *Keep this tab open!* You'll come back here in step 7 to specify your bot's webhook endpoint URL.
34 |
35 | 4) Now that you've got all the credentials, you need to set up an actual IP Messaging client. If you don't already have a native app built, the quickest way to get started is to clone the Twilio IPM client demo, which is available at [https://github.com/twilio/ip-messaging-demo-js](https://github.com/twilio/ip-messaging-demo-js)
36 |
37 | Follow the instructions to get your IP Messaging Demo client up and running using the credentials you collected above.
38 |
39 | 5) Start up the sample Twilio IPM Bot. From inside your cloned Botkit repo, run:
40 | ```
41 | TWILIO_ACCOUNT_SID= TWILIO_AUTH_TOKEN= TWILIO_IPM_SERVICE_SID= TWILIO_API_KEY= TWILIO_API_SECRET= node examples/twilio_ipm_bot.js
42 | ```
43 |
44 | 6) If you are _not_ running your bot at a public, SSL-enabled internet address, use [localtunnel.me](http://localtunnel.me) to make it available to Twilio. Note the URL it gives you. For example, it may say your url is `https://xyx.localtunnel.me/` In this case, the webhook URL for use in step 7 would be `https://xyx.localtunnel.me/twilio/receive`
45 |
46 | 7) Set up a webhook endpoint for your app that uses your public URL, or the URL that localtunnel gave you. This is done on [settings page for your IP Messaging service](https://www.twilio.com/user/account/ip-messaging/services). Enable *all of the POST-event* webhooks events!
47 |
48 | 6) Load your IP Messaging client, and talk to your bot!
49 |
50 | Try:
51 |
52 | * hello
53 | * who am i?
54 | * call me Bob
55 | * shutdown
56 |
57 | ### Things to note
58 |
59 | Since Twilio delivers messages via web hook, your application must be available at a public internet address. Additionally, Twilio requires this address to use SSL. Luckily, you can use [LocalTunnel](https://localtunnel.me/) to make a process running locally or in your dev environment available in a Twilio-friendly way.
60 |
61 | Additionally, you need to enable your Twilio IPM instance's webhook callback events. This can be done via the Twilio dashboard, but can also be done automatically using a Bash script. You can use the sample script below to enable all of the post-event webhook callbacks:
62 |
63 | ```
64 | #!/bin/bash
65 | echo 'please enter the service uri'
66 | read servuri
67 |
68 | echo 'please enter the service sid'
69 | read servsid
70 |
71 | echo 'please enter the account sid'
72 | read accsid
73 |
74 | echo 'please enter the auth token'
75 | read authtok
76 |
77 | onChannelDestroyedCurl="curl -X POST https://ip-messaging.twilio.com/v1/Services/$servsid -d 'Webhooks.OnChannelDestroyed.Url=$servuri/twilio/receive' -d 'Webhooks.OnChannelDestroyed.Method=POST' -d 'Webhooks.OnChannelDestroyed.Format=XML' -u '$accsid:$authtok'"
78 | eval $onChannelDestroyedCurl
79 |
80 | onChannelAddedCurl="curl -X POST https://ip-messaging.twilio.com/v1/Services/$servsid -d 'Webhooks.OnChannelAdded.Url=$servuri/twilio/receive' -d 'Webhooks.OnChannelAdded.Method=POST' -d 'Webhooks.OnChannelAdded.Format=XML' -u '$accsid:$authtok'"
81 | eval $onChannelAddedCurl
82 |
83 | onMemberRemovedCurl="curl -X POST https://ip-messaging.twilio.com/v1/Services/$servsid -d 'Webhooks.OnMemberRemoved.Url=$servuri/twilio/receive' -d 'Webhooks.OnMemberRemoved.Method=POST' -d 'Webhooks.OnMemberRemoved.Format=XML' -u '$accsid:$authtok'"
84 | eval $onMemberRemovedCurl
85 | onMessageRemovedCurl="curl -X POST https://ip-messaging.twilio.com/v1/Services/$servsid -d 'Webhooks.OnMessageRemoved.Url=$servuri/twilio/receive' -d 'Webhooks.OnMessageRemoved.Method=POST' -d 'Webhooks.OnMessageRemoved.Format=XML' -u '$accsid:$authtok'"
86 | eval $onMessageRemovedCurl
87 |
88 | onMessageUpdatedCurl="curl -X POST https://ip-messaging.twilio.com/v1/Services/$servsid -d 'Webhooks.OnMessageUpdated.Url=$servuri/twilio/receive' -d 'Webhooks.OnMessageUpdated.Method=POST' -d 'Webhooks.OnMessageUpdated.Format=XML' -u '$accsid:$authtok'"
89 | eval $onMessageUpdatedCurl
90 |
91 | onChannelUpdatedCurl="curl -X POST https://ip-messaging.twilio.com/v1/Services/$servsid -d 'Webhooks.OnChannelUpdated.Url=$servuri/twilio/receive' -d 'Webhooks.OnChannelUpdated.Method=POST' -d 'Webhooks.OnChannelUpdated.Format=XML' -u '$accsid:$authtok'"
92 | eval $onChannelUpdatedCurl
93 |
94 | onMemberAddedCurl="curl -X POST https://ip-messaging.twilio.com/v1/Services/$servsid -d 'Webhooks.OnMemberAdded.Url=$servuri/twilio/receive' -d 'Webhooks.OnMemberAdded.Method=POST' -d 'Webhooks.OnMemberAdded.Format=XML' -u '$accsid:$authtok'"
95 | eval $onMemberAddedCurl
96 | ```
97 |
98 | When you are ready to go live, consider [LetsEncrypt.org](http://letsencrypt.org), a _free_ SSL Certificate Signing Authority which can be used to secure your website very quickly. It is fabulous and we love it.
99 |
100 |
101 | ## Create a controller
102 |
103 | To connect Botkit to Twilio IPM, use the constructor method, [Botkit.twilioipmbot()](#botkittwilioipmbot).
104 | This will create a Botkit controller with [all core features](core.md#botkit-controller-object) as well as [some additional methods](#additional-controller-methods).
105 |
106 | #### Botkit.twilioipmbot()
107 | | Argument | Description
108 | |--- |---
109 | | config | an object containing configuration options
110 |
111 | Returns a new Botkit controller.
112 |
113 | The `config` argument is an object with these properties:
114 |
115 | | Name | Type | Description
116 | |--- |--- |---
117 | | studio_token | String | An API token from [Botkit Studio](#readme-studio.md)
118 | | debug | Boolean | Enable debug logging
119 |
120 | For example:
121 |
122 | ```javascript
123 | var Botkit = require('botkit');
124 | var controller = Botkit.twilioipmbot({})
125 | ```
126 |
127 | ## Event List
128 |
129 | In addition to the [core events that Botkit fires](core.md#receiving-messages-and-events), this connector also fires some platform specific events.
130 |
131 | Normal messages will be sent to your bot using the `message_received` event. In addition, Botkit will trigger these Botkit-specific events:
132 |
133 | | Event | Description
134 | |--- |---
135 | | bot_channel_join| The bot has joined a channel
136 | | bot_channel_leave | The bot has left a channel
137 | | user_channel_join | A user (not the bot) has joined a channel
138 | | user_channel_leave | A user (not the bot) has left a channel
139 |
140 | Botkit will handle and distribute [all of the Twilio IPM API webhooks events](https://www.twilio.com/docs/api/ip-messaging/webhooks). Your Bot can act on any of these events, and will receive the complete payload from Twilio. Below, is a list of the IPM API callback events that can be subscribed to in your Bot:
141 |
142 | | Event | Description
143 | |--- |---
144 | | onMessageSent | Message sent
145 | | onMessageRemoved | Message removed/deleted
146 | | onMessageUpdated | Message edited
147 | | onChannelAdded | Channel created
148 | | onChannelUpdated | Channel FriendlyName or Attributes updated
149 | | onChannelDestroyed | Channel Deleted/Destroyed
150 | | onMemberAdded | Channel Member Joined or Added
151 | | onMemberRemoved | Channel Member Removed or Left
152 |
153 |
154 | ## Working with Twilio IP Messaging
155 |
156 | Botkit receives messages from Twilio IPM using Webhooks, and sends messages using Twilio's REST APIs. This means that your Bot application must present a web server that is publicly addressable. Everything you need to get started is already included in Botkit.
157 |
158 | 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.
159 |
160 | Here is the complete code for a basic Twilio bot:
161 |
162 | ```javascript
163 | var Botkit = require('botkit');
164 | var controller = Botkit.twilioipmbot({
165 | debug: false
166 | })
167 |
168 | var bot = controller.spawn({
169 | TWILIO_IPM_SERVICE_SID: process.env.TWILIO_IPM_SERVICE_SID,
170 | TWILIO_ACCOUNT_SID: process.env.TWILIO_ACCOUNT_SID,
171 | TWILIO_API_KEY: process.env.TWILIO_API_KEY,
172 | TWILIO_API_SECRET: process.env.TWILIO_API_SECRET,
173 | identity: 'Botkit',
174 | autojoin: true
175 | });
176 |
177 | // if you are already using Express, you can use your own server instance...
178 | // see "Use BotKit with an Express web server"
179 | controller.setupWebserver(process.env.port,function(err,webserver) {
180 | controller.createWebhookEndpoints(controller.webserver, bot, function() {
181 | console.log('This bot is online!!!');
182 | });
183 | });
184 |
185 | // user said hello
186 | controller.hears(['hello'], 'message_received', function(bot, message) {
187 |
188 | bot.reply(message, 'Hey there.');
189 |
190 | });
191 |
192 | controller.hears(['cookies'], 'message_received', function(bot, message) {
193 |
194 | bot.startConversation(message, function(err, convo) {
195 |
196 | convo.say('Did someone say cookies!?!!');
197 | convo.ask('What is your favorite type of cookie?', function(response, convo) {
198 | convo.say('Golly, I love ' + response.text + ' too!!!');
199 | convo.next();
200 | });
201 | });
202 | });
203 | ```
204 |
205 | #### controller.createWebhookEndpoints()
206 |
207 | This function configures the route `https://_your_server_/twilio/receive`
208 | to receive webhooks from twilio.
209 |
210 | This url should be used when configuring Twilio.
211 |
212 | ## System Bots vs User Bots
213 |
214 | Bots inside a Twilio IPM environment can run in one of two ways: as the "system" user,
215 | ever present and automatically available in all channels, OR, as a specific "bot" user
216 | who must be added to channels in order to interact.
217 |
218 | By default, bots are "system" users, and can be configured as below:
219 |
220 | ```javascript
221 | var bot = controller.spawn({
222 | TWILIO_IPM_SERVICE_SID: process.env.TWILIO_IPM_SERVICE_SID,
223 | TWILIO_ACCOUNT_SID: process.env.TWILIO_ACCOUNT_SID,
224 | TWILIO_API_KEY: process.env.TWILIO_API_KEY,
225 | TWILIO_API_SECRET: process.env.TWILIO_API_SECRET,
226 | });
227 | ```
228 |
229 | To connect as a "bot" user, pass in an `identity` field:
230 |
231 | ```javascript
232 | var bot = controller.spawn({
233 | TWILIO_IPM_SERVICE_SID: process.env.TWILIO_IPM_SERVICE_SID,
234 | TWILIO_ACCOUNT_SID: process.env.TWILIO_ACCOUNT_SID,
235 | TWILIO_API_KEY: process.env.TWILIO_API_KEY,
236 | TWILIO_API_SECRET: process.env.TWILIO_API_SECRET,
237 | identity: 'My Bot Name',
238 | });
239 | ```
240 |
241 | To have your bot automatically join every channel as they are created and removed,
242 | pass in `autojoin`:
243 |
244 | ```javascript
245 | var bot = controller.spawn({
246 | TWILIO_IPM_SERVICE_SID: process.env.TWILIO_IPM_SERVICE_SID,
247 | TWILIO_ACCOUNT_SID: process.env.TWILIO_ACCOUNT_SID,
248 | TWILIO_API_KEY: process.env.TWILIO_API_KEY,
249 | TWILIO_API_SECRET: process.env.TWILIO_API_SECRET,
250 | identity: 'Botkit',
251 | autojoin: true
252 | });
253 | ```
254 |
255 | ## Using the Twilio API
256 |
257 | You can use the Twilio API directly in your Bot via Botkit's bot.api object. Botkit's bot.api provides a thin wrapper on the [Twilio official module](http://twilio.github.io/twilio-node/).
258 |
259 | For example, to [retrieve a member from a channel](https://www.twilio.com/docs/api/ip-messaging/rest/members#action-get) using the un-wrapped Twilio API client, you would use the following code:
260 |
261 | ```javascript
262 | service.channels('CHANNEL_SID').members('MEMBER_SID').get().then(function(response) {
263 | console.log(response);
264 | }).fail(function(error) {
265 | console.log(error);
266 | });
267 | ```
268 |
269 | In Botkit, this can be accomplished by simply replacing the reference to a `service` object, with the `bot.api` object, as shown here:
270 |
271 | ```javascript
272 | bot.api.channels('CHANNEL_SID').members('MEMBER_SID').get().then(function(response) {
273 | console.log(response);
274 | }).fail(function(error) {
275 | console.log(error);
276 | });
277 | ```
278 | This gives you full access to all of the Twilio API methods so that you can use them in your Bot.
279 |
280 | Here is an example showing how to join a channel using Botkit's bot.api object, which creates a member to the channel, by wrapping the IPM API.
281 |
282 | ```javascript
283 | controller.on('onChannelAdded', function(bot, message){
284 | // whenever a channel gets added, join it!
285 | bot.api.channels(message.channel).members.create({
286 | identity: bot.identity
287 | }).then(function(response) {
288 |
289 | }).fail(function(error) {
290 | console.log(error);
291 | });
292 | });
293 | ```
294 |
--------------------------------------------------------------------------------
/docs/readme-twiliosms.md:
--------------------------------------------------------------------------------
1 | # Botkit and Twilio Programmable SMS
2 |
3 | # Getting Started
4 |
5 | 1) Install Botkit [more info here](core.md#installation)
6 |
7 | 2) [Register a developer account with Twilio](/docs/provisioning/twilio-sms.md). Once you've got it, head to the [Get Started with SMS](https://www.twilio.com/console/sms/getting-started/basics) page in your Twilio Console.
8 |
9 | After completing the tutorial above you should have all three values to get your bot running: A **Twilio Account SID**, a **Twilio Auth Token**, and a **Twilio Number**.
10 |
11 | **Twilio Account SID and Auth Token**
12 |
13 | These values are available on your [Twilio Account Settings](https://www.twilio.com/user/account/settings) page on the Twilio Console. Copy both the SID and token values (located under API Credentials)
14 |
15 | **Twilio Number**
16 |
17 | You should have purchased a Twilio Number. You will send/receive messages using this phone number. Example: `+19098765432`
18 |
19 | 3) Configure your Twilio Number. Head to the [Phone Numbers](https://www.twilio.com/console/phone-numbers) in your Twilio Console and select the phone number you will use for your SMS bot.
20 |
21 | Under the *Messaging* section, select "Webhooks/TwiML" as your *Configure with* preference. Two more fields will pop up: ***A message comes in***, and ***Primary handler fails***.
22 |
23 | The first one is the type of handler you will use to respond to Twilio webhooks. Select "Webhook" and input the URI of your endpoint (e.g. `https://mysmsbot.localtunnel.me/sms/receive`) and select `HTTP POST` as your handling method.
24 |
25 | Twilio will send `POST` request to this address every time a user sends an SMS to your Twilio Number.
26 |
27 | > By default Botkit will serve content from `https://YOURSERVER/sms/receive`. If you are not running your bot on a public, SSL-enabled internet address, you can use a tool like [ngrok.io](http://ngrok.io/) or [localtunnel.me](localtunnel.me) to expose your local development enviroment to the outside world for the purposes of testing your SMS bot.
28 |
29 | The second preference ("Primary handler fails") is your backup plan. The URI Twilio should `POST` to in case your primary handler is unavailable. You can leave this field in blank for now but keep in mind this is useful for error handling (e.g. to notify users that your bot is unavailable).
30 |
31 | 4) Run the example Twilio SMS bot included in Botkit's repository ([twilio_sms_bot.js](../examples/twilio_sms_bot.js)). Copy and paste the example bot's code into a new JavaScript file (e.g. `twilio_sms_bot.js`) in your current working directory and run the following command on your terminal:
32 |
33 | ```bash
34 | $ TWILIO_ACCOUNT_SID= TWILIO_AUTH_TOKEN= TWILIO_NUMBER= node twilio_sms_bot.js
35 | ```
36 |
37 | > Note: Remember to run localtunnel or ngrok to expose your local development environment to the outside world. For example, in localtunnel run `lt --port 5000 --subdomain mysmsbot` (See note on step 4)
38 |
39 | 6) Your bot should be online! Grab your phone and text `hi` to your Twilio Number and you will get a `Hello.` message back!
40 |
41 | ## Create a controller
42 |
43 | To connect Botkit to Twilio SMS, use the constructor method, [Botkit.twiliosmsbot()](#botkittwiliosmsbot).
44 | This will create a Botkit controller with [all core features](core.md#botkit-controller-object) as well as [some additional methods](#additional-controller-methods).
45 |
46 | #### Botkit.twiliosmsbot()
47 | | Argument | Description
48 | |--- |---
49 | | config | an object containing configuration options
50 |
51 | Returns a new Botkit controller.
52 |
53 | The `config` argument is an object with these properties:
54 |
55 | | Name | Type | Description
56 | |--- |--- |---
57 | | studio_token | String | An API token from [Botkit Studio](#readme-studio.md)
58 | | debug | Boolean | Enable debug logging
59 | | account_sid | found in your [Twilio Console Dashboard](https://www.twilio.com/console)
60 | | auth_token | found in your [Twilio Console Dashboard](https://www.twilio.com/console)
61 | | twilio_number | your app's phone number, found in your [Phone Numbers Dashboard](https://www.twilio.com/console/phone-numbers/dashboard) **The phone number format must be: `+15551235555`**
62 |
63 |
64 | For example:
65 |
66 | ```javascript
67 | var Botkit = require('botkit');
68 | var controller = Botkit.twiliosmsbot({
69 | account_sid: process.env.TWILIO_ACCOUNT_SID,
70 | auth_token: process.env.TWILIO_AUTH_TOKEN,
71 | twilio_number: process.env.TWILIO_NUMBER
72 | })
73 | ```
74 |
75 | ## Usage
76 |
77 | *Note: This document assumes that you are familiarized with Botkit and Twilio's Programmable SMS API*
78 |
79 | To connect your bot to Twilio you must point a Messaging webhook to http://your_host/sms/receive, after doing so, every Twilio message will be sent to that address.
80 |
81 | Then you need to write your bot. First, create a TwilioSMSBot instance and pass an object with your configuration properties:
82 |
83 | * `account_sid`: found in your [Twilio Console Dashboard](https://www.twilio.com/console)
84 | * `auth_token`: found in your [Twilio Console Dashboard](https://www.twilio.com/console)
85 | * `twilio_number`: your app's phone number, found in your [Phone Numbers Dashboard](https://www.twilio.com/console/phone-numbers/dashboard) **The phone number format must be: `+15551235555`**
86 |
87 | ```js
88 | const Botkit = require('botkit')
89 | const controller = Botkit.twiliosmsbot({
90 | account_sid: process.env.TWILIO_ACCOUNT_SID,
91 | auth_token: process.env.TWILIO_AUTH_TOKEN,
92 | twilio_number: process.env.TWILIO_NUMBER
93 | })
94 | ```
95 |
96 | `spawn()` your bot instance:
97 |
98 | ```js
99 | let bot = controller.spawn({})
100 | ```
101 |
102 | Then you need to set up your Web server and create the webhook endpoints so your app can receive Twilio's messages:
103 |
104 | ```js
105 | controller.setupWebserver(process.env.PORT, function (err, webserver) {
106 | controller.createWebhookEndpoints(controller.webserver, bot, function () {
107 | console.log('TwilioSMSBot is online!')
108 | })
109 | })
110 | ```
111 |
112 | And finally, you can setup listeners for specific messages, like you would in any other `botkit` bot:
113 |
114 | ```js
115 | controller.hears(['hi', 'hello'], 'message_received', (bot, message) => {
116 | bot.startConversation(message, (err, convo) => {
117 | convo.say('Hi, I am Oliver, an SMS bot! :D')
118 | convo.ask('What is your name?', (res, convo) => {
119 | convo.say(`Nice to meet you, ${res.text}!`)
120 | convo.next()
121 | })
122 | })
123 | })
124 |
125 | controller.hears('.*', 'message_received', (bot, message) => {
126 | bot.reply(message, 'huh?')
127 | })
128 | ```
129 |
130 | See full example in the `examples` directory of this repo.
131 |
132 | ### Sending media attachments (MMS)
133 |
134 | To send media attachments, pass a `mediaUrl` property to any of Botkit's outgoing messages functions (`reply`, `say`, `ask`, etc.) with an optional `text` property for text that goes along with your attachment.
135 |
136 | ```js
137 | /*
138 | Sending an attachment
139 | */
140 | bot.reply(message, {
141 | text: 'Optional text to go with attachment',
142 | mediaUrl: 'https://i.imgur.com/9n3qoKx.png'
143 | })
144 | ```
145 |
146 | > Note: your Twilio number as well as the recipient's phone must support MMS for media attachments to work
147 |
148 | For more details on outgoing media attachments and a full list of accepted MIME types, go to [Twilio's docs on media attachment](https://www.twilio.com/docs/api/rest/accepted-mime-types).
149 |
--------------------------------------------------------------------------------
/docs/readme-web.md:
--------------------------------------------------------------------------------
1 | # Botkit Web Connector
2 |
3 | The power of bots and conversational software can included in any website or app using Botkit's new connector!
4 |
5 | ## What is this?
6 |
7 | This connector provides a basic interface for Botkit to send and receive messages directly, rather than relying on a third party messaging service like Slack or Facebook messenger.
8 | It includes a built-in chat server that can send and receive messages using real-time websocket connections or asynchronous webhooks.
9 | This allows Botkit bots to live on the web, or be embedded into websites and native mobile apps.
10 |
11 | The functionality provided in the connector is actually very simple, and requires integration with a webserver (to serve the application and host the chat server) and a front-end client (to provide a user interface and render messages). These components are provided in a separate project, [Botkit Anywhere](https://github.com/howdyai/botkit-starter-web).
12 |
13 | ## Getting Started
14 |
15 | Everything you need to build your bot is included in [Botkit Anywhere](https://github.com/howdyai/botkit-starter-web),
16 | a boilerplate application that includes all the components needed to operate your bot, as well as sample code and extra features.
17 |
18 | * All the features of Botkit Core
19 | * A built-in chat server that can handle thousands of simultaneous conversations
20 | * A customizable front-end chat client built with HTML, CSS, and Javascript
21 | * A webserver for serving the application to users and hosting your bot's business logic
22 |
23 | **Most developers should start with [the starter kit](https://github.com/howdyai/botkit-starter-web) rather than make direct use of the Botkit core library.**
24 |
25 | # Developing with Botkit for the Web
26 |
27 | ## Create a Controller
28 |
29 | Use the Botkit Anywhere constructor method, [Botkit.anywhere()](#botkitanywhere).
30 | This will create a Botkit controller with [all core features](core.md#botkit-controller-object) as well as [some additional methods](#additional-controller-methods).
31 |
32 | #### Botkit.anywhere()
33 | | Argument | Description
34 | |--- |---
35 | | config | an object containing configuration options
36 |
37 | Returns a Botkit controller that works with Botkit Anywhere.
38 |
39 | The `config` argument is an object with these properties:
40 |
41 | | Name | Type | Description
42 | |--- |--- |---
43 | | studio_token | String | An API token from [Botkit Studio](#readme-studio.md)
44 | | debug | Boolean | Enable debug logging
45 | | replyWithTyping | Boolean | Send typing indicators automatically (default false)
46 | | typingDelayFactor | Float | Adjust the speed of the typing delay
47 |
48 | For example:
49 |
50 | ```javascript
51 | var controller = Botkit.anywhere({
52 | debug: false,
53 | replyWithTyping: true,
54 | studio_token: process.env.studio_token,
55 | typingDelayFactor: 1.3
56 | });
57 | ```
58 |
59 | ## Event List
60 |
61 | When using [Botkit Anywhere](https://github.com/howdyai/botkit-starter-web) and the built-in [web chat client](https://github.com/howdyai/botkit-starter-web/blob/master/docs/botkit_web_client.md), Botkit will fire a small number of native events.
62 |
63 | ### Built-in Events
64 |
65 | | Event | Description
66 | |-- |--
67 | | message_received | the bot has received a message
68 | | hello | a new user has connected to the bot
69 | | welcome_back | a returning user has established a new connection to the bot
70 | | reconnect | an ongoing user session has experienced a disconnect/reconnect
71 |
72 | ### Custom Events
73 |
74 | Developers may also fire custom events from the web client. Custom events triggered in the front-end client will arrive at the Botkit app based on their `type` field.
75 |
76 | Custom events like this can be used to build new methods for your user to interact with the bot, such as buttons or other interactive elements.
77 |
78 | ### Message Objects
79 |
80 | The message objects used by Botkit Web are essentially "pure" Botkit messages, containing a few primary fields:
81 |
82 | | Field | Description
83 | |-- |--
84 | | user | a unique user id for the user
85 | | text | the text of the message
86 | | type | type of message or event
87 |
88 | Botkit has a very liberal policy on adding additional fields to the message object, so depending on the implementation details of the front-end client, other fields may be present!
89 |
90 | In addition, the built-in web chat client feature support for quick replies and file attachments to be included in messages.
91 |
92 | ## Quick Replies
93 |
94 | Quick replies are buttons that appear at the bottom of the message client, and offer suggested replies to the user. Clicking a quick reply is essentially the same as the user typing the suggested reply and sending it as a message.
95 |
96 | To add quick replies to Botkit Web messages, include a `quick_replies` field that includes an array of objects, each with a `title` and a `payload`. The title will displayed on the button itself, while the payload is the actual text sent back to the bot by the user.
97 |
98 | ```js
99 | var reply = {
100 | text: 'Look, quick replies!',
101 | quick_replies: [
102 | {
103 | title: 'Hello',
104 | payload: 'hello'
105 | },
106 | {
107 | title: 'Help',
108 | payload: 'help'
109 | },
110 | ]
111 | }
112 | ```
113 |
114 |
115 | ## File Attachments
116 |
117 | Files can be attached to Botkit Web messages by adding a `files` field that includes an array of objects, each with a `url` and an `image` field. The url field should contain a valid URL, and the image should be set to `true` if the file is an image.
118 |
119 | ```js
120 | var reply = {
121 | text: 'Look, an image!',
122 | files: [
123 | {
124 | url: 'http://tableflipper.com/IRX2.gif',
125 | image: true
126 | }
127 | ]
128 | }
129 | ```
130 |
131 | ## Additional Controller Methods
132 |
133 | Botkit on the web works much the same as it does on all the other platforms. Developers have full access to all of [Botkit's core features](core.md) -
134 | and a few extra ones that are specific to operating on the web!
135 |
136 | #### controller.openSocketServer(webserver_instance, websocket_server_options)
137 |
138 | This function takes an instance of an http server object - that is, the results of a call to `http.createServer()`.
139 |
140 | The second parameter is an object for additional options to pass to the constructor of the websocket server. [Additional options for the websocket server found here.](https://www.npmjs.com/package/ws#api-docs)
141 |
142 | Example - Add client tracking to websocker server:
143 |
144 | ```js
145 | var server = http.createServer();
146 |
147 | var wsOptions = {
148 | clientTracking: true
149 | }
150 |
151 | controller.openSocketServer(server, wsOptions);
152 | ```
153 |
154 | It connects a `ws` powered websocket server to the web server, and allows the application to accept socket connections directly with the bot.
155 |
156 | [A compatible webserver is provided in the starter kit](https://github.com/howdyai/botkit-starter-web/blob/master/components/express_webserver.js).
157 |
158 | #### controller.setTypingDelayFactor(delayFactor);
159 |
160 | Adjust the speed of the typing delay by setting a factor. The typing delay determines the time that the bot takes, to reply to a message. By default, the factor is set to 1, using a predefined calculation for the typing delay, that takes the message length into account. In order to increase or decrease the typing delay, the factor can be changed. For example, the default typing delay can be doubled by setting the factor to 2.
161 |
162 | **For example:**
163 |
164 | ```
165 | // double the time of the typing delay
166 | controller.setTypingDelayFactor(2);
167 | ```
168 |
169 | ## Additional Bot Instance Methods
170 |
171 | #### bot.replyWithTyping(message, reply)
172 |
173 | This works just like the normal `bot.reply()`, but instead of sending the message immediately, sends a typing indicator first, then waits for a short period before sending the actual message.
174 |
--------------------------------------------------------------------------------
/docs/readme-webex.md:
--------------------------------------------------------------------------------
1 | # Botkit and Webex Teams
2 |
3 | Table of Contents
4 |
5 | * [Getting Started](#getting-started)
6 | * [Create a Controller](#create-a-controller)
7 | * [Webex-specific Events](#webex-specific-events)
8 | * [Message Formatting](#message-formatting)
9 | * [Attaching Files](#attaching-files)
10 | * [Receiving Files](#receiving-files)
11 | * [Starting Direct Messages](#starting-direct-messages)
12 |
13 | *Note*: Documentation for the legacy, pre-rebrand [Cisco Spark version of Botkit is here.](readme-ciscospark.html)
14 |
15 | ## Getting Started
16 |
17 | 1. [Install Botkit on your computer](/getstarted.html)
18 |
19 | 2. Create a Botkit powered Node app:
20 |
21 | * [Remix the starter project on Glitch](https://glitch.com/~botkit-cisco-webex-teams)
22 | * Or: Use the command line tool:
23 |
24 | ```
25 | botkit new --platform webex
26 | ```
27 |
28 | 3. [Follow this guide to configuring the Cisco Webex Teams API](/docs/provisioning/cisco-spark.md)
29 |
30 | ## Working with Webex
31 |
32 | Botkit receives messages from the Cisco Webex cloud platform using webhooks, and sends messages using their APIs. This means that your bot application must present a web server that is publicly addressable. Everything you need to get started is already included in Botkit.
33 |
34 | To connect your bot to Webex, [get an access token here](https://developer.webex.com/add-bot.html). In addition to the access token,
35 | Webex bots require a user-defined `secret` which is used to validate incoming webhooks, as well as a `public_address` which is the URL at which the bot application can be accessed via the internet.
36 |
37 | Each time the bot application starts, Botkit will register a webhook subscription.
38 | Botkit will automatically manage your bot's webhook subscriptions, but if you plan on having multiple instances of your bot application with different URLs (such as a development instance and a production instance), use the `webhook_name` field with a different value for each instance.
39 |
40 | Bots in Webex are identified by their email address, and can be added to any space in any team or organization. If your bot should only be available to users within a specific organization, use the `limit_to_org` or `limit_to_domain` options.
41 | 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.
42 |
43 | The full code for a simple Webex bot is below:
44 |
45 | ~~~javascript
46 | var Botkit = require('botkit');
47 |
48 | var controller = Botkit.webexbot({
49 | debug: true,
50 | log: true,
51 | public_address: process.env.public_address,
52 | access_token: process.env.access_token,
53 | secret: process.env.secret
54 | });
55 |
56 | var bot = controller.spawn({});
57 |
58 | controller.setupWebserver(process.env.PORT || 3000, function(err, webserver) {
59 | controller.createWebhookEndpoints(webserver, bot, function() {
60 | console.log("Webhooks set up!");
61 | });
62 | });
63 |
64 | controller.hears('hello', 'direct_message,direct_mention', function(bot, message) {
65 | bot.reply(message, 'Hi');
66 | });
67 |
68 | controller.on('direct_mention', function(bot, message) {
69 | bot.reply(message, 'You mentioned me and said, "' + message.text + '"');
70 | });
71 |
72 | controller.on('direct_message', function(bot, message) {
73 | bot.reply(message, 'I got your private message. You said, "' + message.text + '"');
74 | });
75 | ~~~
76 |
77 | ## Create a Controller
78 |
79 | When creating the Botkit controller, there are several platform-specific options available.
80 |
81 | ### Botkit.webexbot
82 | | Argument | Description
83 | |--- |---
84 | | public_address | _required_ the root url of your application (https://mybot.com)
85 | | `access_token` | _required_ token provided by Webex for your bot
86 | | secret | _required_ secret for validating webhooks originate from Webex
87 | | webhook_name | _optional_ name for webhook configuration on Webex side. Providing a name here allows for multiple bot instances to receive the same messages. Defaults to 'Botkit Firehose'
88 | | `limit_to_org` | _optional_ organization id in which the bot should exist. If user from outside org sends message, it is ignored
89 | | `limit_to_domain` | _optional_ email domain (@howdy.ai) or array of domains [@howdy.ai, @botkit.ai] from which messages can be received
90 |
91 | ~~~javascript
92 | var controller = Botkit.webexbot({
93 | debug: true,
94 | log: true,
95 | public_address: 'https://mybot.ngrok.io',
96 | access_token: process.env.access_token,
97 | secret: 'randomstringofnumbersandcharacters12345',
98 | webhook_name: 'dev',
99 | limit_to_org: 'my_webex_org_id',
100 | limit_to_domain: ['@howdy.ai','@cisco.com'],
101 | });
102 | ~~~
103 |
104 |
105 | ## Webex Specific Events
106 |
107 | All events [listed here](https://developer.webex.com/webhooks-explained.html#resources-events) should be expected, in the format `resource`.`event` - for example, `rooms.created`.
108 |
109 | In addition, the following custom Botkit-specific events are fired:
110 |
111 | | Event | Description
112 | |--- |---
113 | | direct_message | Bot has received a message as a DM
114 | | direct_mention | Bot has been mentioned in a public space
115 | | self_message | Bot has received a message it sent
116 | | user_space_join | a user has joined a space in which the bot is present
117 | | bot_space_join | the bot has joined a new space
118 | | user_space_leave | a user has left a space in which the bot is present
119 | | bot_space_leave | the bot has left a space
120 |
121 |
122 | ## Message Formatting
123 |
124 | Webex supports both a `text` field and a `markdown` field for outbound messages. [Read here for details on Webex's markdown support.](https://developer.webex.com/formatting-messages.html)
125 |
126 | To specify a markdown version, add it to your message object:
127 |
128 | ~~~javascript
129 | bot.reply(message,{text: 'Hello', markdown: '*Hello!*'});
130 | ~~~
131 |
132 | ## Attaching Files
133 |
134 | Files can be attached to outgoing messages in one of two ways.
135 |
136 | *Specify URL*
137 |
138 | If the file you wish to attach is already available online, simply specify the URL in the `files` field of the outgoing message:
139 |
140 | ~~~javascript
141 | bot.reply(message,{text:'Here is your file!', files:['http://myserver.com/file.pdf']});
142 | ~~~
143 |
144 | *Send Local File*
145 |
146 | If the file you wish to attach is present only on the local server, attach it to the message as a readable stream:
147 |
148 | ~~~javascript
149 | var fs = require('fs');
150 | bot.reply(message,{text: 'I made this file for you.', files:[fs.createReadStream('./newfile.txt')]});
151 | ~~~
152 |
153 | ## Receiving files
154 |
155 | Your bot may receive messages with files attached. Attached files will appear in an array called `message.data.files`.
156 |
157 | Botkit provides 2 methods for retrieving information about the file.
158 |
159 | ### bot.retrieveFileInfo(url, cb)
160 | | Parameter | Description
161 | |--- |---
162 | | url | url of file from message.data.files
163 | | cb | callback function in the form function(err, file_info)
164 |
165 | The callback function will receive an object with fields like `filename`, `content-type`, and `content-length`.
166 |
167 | ~~~javascript
168 | controller.on('direct_message', function(bot, message) {
169 | bot.reply(message, 'I got your private message. You said, "' + message.text + '"');
170 | if (message.data.files) {
171 | bot.retrieveFileInfo(message.data.files[0], function(err, file_info) {
172 | bot.reply(message,'I also got an attached file called ' + file_info.filename);
173 | });
174 | }
175 | });
176 | ~~~
177 |
178 | ### bot.retrieveFile(url, cb)
179 | | Parameter | Description
180 | |--- |---
181 | | url | url of file from message.data.files
182 | | cb | callback function in the form function(err, file_content)
183 |
184 | The callback function will receive the full content of the file.
185 |
186 | ~~~javascript
187 | controller.on('direct_message', function(bot, message) {
188 | bot.reply(message, 'I got your private message. You said, "' + message.text + '"');
189 | if (message.data.files) {
190 | bot.retrieveFileInfo(message.data.files[0], function(err, file_info) {
191 | if (file_info['content-type'] == 'text/plain') {
192 | bot.retrieveFile(message.data.files[0], function(err, file) {
193 | bot.reply(message,'I got a text file with the following content: ' + file);
194 | });
195 | }
196 | });
197 | }
198 | });
199 | ~~~
200 |
201 | ## Starting Direct Messages
202 |
203 | Webex's API provides several ways to send private messages to users -
204 | by the user's email address, or by their user id. These may be used in the case where the
205 | user's email address is unknown or unavailable, or when the bot should respond to the `actor`
206 | instead of the `sender` of a message.
207 |
208 | For example, a bot may use these methods when handling a `bot_space_join` event
209 | in order to send a message to the _user who invited the bot_ (the actor) instead of
210 | the bot itself (the sender).
211 |
212 | NOTE: Core functions like [bot.startPrivateConversation()](readme.md#botstartprivateconversation) work as expected,
213 | and will create a direct message thread with the sender of the incoming_message.
214 |
215 | ### bot.startPrivateConversationWithPersonId()
216 | | Parameter | Description
217 | |--- |---
218 | | personId | the personId of the user to whom the bot should send a message
219 | | cb | callback function in the form function(err, file_content)
220 |
221 | Use this function to send a direct message to a user by their personId, which
222 | can be found in message and event payloads at the following location:
223 |
224 | ~~~javascript
225 | var personId = message.original_message.actorId;
226 | ~~~
227 |
228 | ### bot.startPrivateConversationWithActor())
229 | | Parameter | Description
230 | |--- |---
231 | | incoming_message | a message or event that has an actorId defined in message.original_message.actorId
232 | | cb | callback function in the form function(err, file_content)
233 |
234 | ~~~javascript
235 | controller.on('bot_space_join', function(bot, message) {
236 | bot.startPrivateConversationWithActor(message, function(err, convo) {
237 | convo.say('The bot you invited has joined the channel.');
238 | });
239 | });
240 | ~~~
241 |
242 |
243 | ### Webex rebrand
244 |
245 | Back in April 2018, Cisco announced a [rebrand from Cisco Spark to Webex](https://developer.webex.com/blog/blog-details-9738.html).
246 | In May 2018, starting with version 0.6.17, Botkit reflected this rebrand by updated 'Spark' mentions from the framework API.
247 |
248 | **For backward compatibility purposes**, several references are now marked as deprecated, but still supported (except for Typescript code). Please migrate your code if your find references to:
249 | - Botkit.sparkbot() => Botkit.webexbot()
250 | - controller.config.ciscospark_access_token => controller.config.access_token: a warning shows up in the console if your code is still using this option.
251 |
252 | **Breaking changes**
253 | - bot.type now equals 'webex' instead of 'ciscospark': there should not be any impact in your code.
254 | - the webhook HTTP endpoint automatically created and exposed by Botkit has been changed from '/ciscospark/receive' to '/webex/receive'. Note that this change can have an impact for the Webex Cloud platform to reach your bot if the traffic to your bot is routed by a reverse proxy. _To avoid any bot to break, the Botkit Webex connector will expose an HTTP endpoint with the deprecated '/ciscospark/receive' path if the 'ciscospark_access_token' configuration property is detected._
--------------------------------------------------------------------------------
/docs/slack-events-api.md:
--------------------------------------------------------------------------------
1 | # Configure Botkit and the Slack Events API
2 |
3 | Building a bot with Botkit and the Slack Events API gives you access to all
4 | of the best tools and options available to create the best and most feature
5 | rich bot.
6 |
7 | In order to get everything set up, you will need to configure a "Slack App"
8 | inside the [Slack Developer Portal](http://api.slack.com/apps), and at the same time,
9 | configure a [Botkit-powered bot](http://botkit.ai). It only takes a few moments,
10 | but there are a bunch of steps!
11 |
12 | ## 1) Create a Slack App
13 |
14 | Go to [http://api.slack.com/apps](http://api.slack.com/apps) and create a new application record.
15 | You will receive a `clientId` and a `clientSecret`. You need these values - copy them into a temporary text file
16 | for use in the following steps.
17 |
18 | ## 2) Turn on your Botkit app
19 |
20 | Now that you've got your clientId and clientSecret, you can start your Botkit app.
21 | Assuming you are using the [Botkit Slack Starter Kit](https://github.com/howdyai/botkit-starter-slack),
22 | this can be done by passing the values in via the command line:
23 |
24 | ```
25 | clientId= clientSecret= PORT=3000 node .
26 | ```
27 |
28 | This will cause the Botkit application to boot up and start listening for messages via incoming web hooks.
29 |
30 | With the Events API, Slack will send all information to your bot via simple
31 | web hooks. To receive web hooks, you will need a public internet address that is
32 | SSL-enabled.
33 |
34 | During development, you can use a tool like [ngrok.io](http://ngrok.io) or [localtunnel.me](http://localtunnel.me)
35 | to temporarily expose your development environment to the public internet.
36 | However, once you go live, you will need a real, stable address.
37 |
38 | In the end, you will have a known url - for example `https://my-dev-bot.ngrok.io` -
39 | that you will use to finish the configuration inside Slack.
40 |
41 | ## 3) Configure oauth
42 |
43 | Botkit and Slack use the oauth authentication system to grant bots access to
44 | connect to, read from, and send messages to Slack teams.
45 |
46 | Click on the "Oauth & Permissions" tab in your Slack's app setting, and under
47 | Redirect URLs, add: `https://my-bot-url/oauth`, then click save.
48 |
49 | ## 4) Add a Bot User
50 |
51 | Click on the "Bot Users" tab and specify a name for your bot. This is the name
52 | that will be used by default when your application creates a new bot on a user's
53 | team.
54 |
55 | In addition to a name, enable the option for "Always Show My Bot Online."
56 |
57 | ## 5) Set up Interactive messages
58 |
59 | "Interactive messages" is Slack's fancy way of saying "buttons."
60 |
61 | In order to enable buttons, click on the "Interactive Components" tab and under Request URL, add `https://my-bot-url/slack/receive`, then click save.
62 |
63 | ## 6) Set up Event Subscriptions
64 |
65 | To start receiving messages, enable event subscriptions. First, under Request URL,
66 | add `https://my-bot-url/slack/receive`. When you finish typing, Slack will verify
67 | that this endpoint is properly configured. You must be running your Botkit application,
68 | and the application must be accessible at the URL specified for this to work.
69 |
70 | Once verified, click "Add Bot User Event", and using the dropdown that appears,
71 | select all of the message.* events: `message.channels`, `message.groups`, `message.im`, `message.mpim`.
72 | This tells Slack to send your bot all messages that are sent in any channel or group
73 | in which your bot is present. Add other events as needed.
74 |
75 | Finally, scroll to the top of the page and switch "Enable Events" to "on".
76 | Your bot is now ready to receive messages!
77 |
78 | ## 7) Add your bot to your Slack team
79 |
80 | Now that your bot is configured, and your application is up and running,
81 | you can login and add your bot. Visit `https://my-bot-url/login`, and you
82 | will be automatically directed to Slack's login page. Login and choose a team.
83 | You'll get one more confirmation before being redirected back to your app.
84 |
85 | Meanwhile, your bot should appear inside your Slack team! You should receive
86 | a friendly welcome message!
87 |
--------------------------------------------------------------------------------
/docs/starterkits.md:
--------------------------------------------------------------------------------
1 | # Botkit Starter Kits
2 |
3 | ## [Botkit Anywhere](https://github.com/howdyai/botkit-starter-web)
4 |
5 | Build a bot for the web and embed it in your site or native application.
6 |
7 | ## [Facebook Starter Kit](https://github.com/howdyai/botkit-starter-facebook)
8 |
9 | Everything you need to build a Facebook Messenger bot
10 |
11 | ## [Slack Starter Kit](https://github.com/howdyai/botkit-starter-slack)
12 |
13 | Everything you need to build a Slack application or custom internal integration
14 |
15 | ## [Microsoft Teams Starter Kit](https://github.com/howdyai/botkit-starter-teams)
16 |
17 | Everything you need to build a bot, compose extension or tab for Microsoft Teams
18 |
19 | ## [Cisco Webex Teams Starter Kit](https://github.com/howdyai/botkit-starter-ciscospark)
20 |
21 | Everything you need to build a custom bot for Cisco Spark
22 |
23 |
--------------------------------------------------------------------------------
/docs/storage.md:
--------------------------------------------------------------------------------
1 | # Storing Information
2 |
3 | Botkit has a built in storage system used to keep data on behalf of users and teams between sessions. Botkit uses this system automatically when storing information for Slack Button applications (see below).
4 |
5 | By default, Botkit will use [json-file-store](https://github.com/flosse/json-file-store) to keep data in JSON files in the filesystem of the computer where the bot is executed. (Note this will not work on Heroku or other hosting systems that do not let node applications write to the file system.) Initialize this system when you create the bot:
6 | ```javascript
7 | var controller = Botkit.slackbot({
8 | json_file_store: 'path_to_json_database'
9 | });
10 | ```
11 |
12 | This system supports freeform storage on a team-by-team, user-by-user, and channel-by-channel basis. Basically ```controller.storage``` is a key value store. All access to this system is through the following twelve functions. Example usage:
13 | ```javascript
14 | controller.storage.users.save({id: message.user, foo:'bar'}, function(err) { ... });
15 | controller.storage.users.get(id, function(err, user_data) {...});
16 | controller.storage.users.delete(id, function(err) {...});
17 | controller.storage.users.all(function(err, all_user_data) {...});
18 |
19 | controller.storage.channels.save({id: message.channel, foo:'bar'}, function(err) { ... });
20 | controller.storage.channels.get(id, function(err, channel_data) {...});
21 | controller.storage.channels.delete(id, function(err) {...});
22 | controller.storage.channels.all(function(err, all_channel_data) {...});
23 |
24 | controller.storage.teams.save({id: message.team, foo:'bar'}, function(err) { ... });
25 | controller.storage.teams.get(id, function(err, team_data) {...});
26 | controller.storage.teams.delete(id, function(err) {...});
27 | controller.storage.teams.all(function(err, all_team_data) {...});
28 | ```
29 |
30 | Note that save must be passed an object with an id. It is recommended to use the team/user/channel id for this purpose.
31 | ```[user/channel/team]_data``` will always be an object while ```all_[user/channel/team]_data``` will always be a list of objects.
32 |
33 | ## Writing your own storage module
34 |
35 | If you want to use a database or do something else with your data,
36 | you can write your own storage module and pass it in.
37 |
38 | Make sure your module returns an object with all the methods. See [simple_storage.js](https://github.com/howdyai/botkit/blob/master/lib/storage/simple_storage.js) for an example of how it is done!
39 |
40 | Then, use it when you create your bot:
41 | ```javascript
42 | var controller = Botkit.slackbot({
43 | storage: my_storage_provider
44 | })
45 | ```
46 |
--------------------------------------------------------------------------------
/docs/studio.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/howdyai/botkit-docs/6569c40ec68762ae526cd2d4987765944f8c5cee/docs/studio.png
--------------------------------------------------------------------------------
/docs/studio_script_author2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/howdyai/botkit-docs/6569c40ec68762ae526cd2d4987765944f8c5cee/docs/studio_script_author2.png
--------------------------------------------------------------------------------
/docs/toc.md:
--------------------------------------------------------------------------------
1 | Features:
2 |
3 | * conversation management
4 | * studio-powered
5 | * simple replies
6 | * building convos in code
7 | * events system
8 | * Hearing
9 | * Other events
10 | * Triggering events
11 | * Platform adapters
12 | * how to build an adapter
13 | * Building plugins
14 | * middlewares
15 | * adding web endpoints
16 | * static assets
17 | * adding toolbar menu items
18 | * message handling/normalizing pipeline
19 |
--------------------------------------------------------------------------------
/docs/what_is_a_bot.md:
--------------------------------------------------------------------------------
1 | # What is a bot?
2 |
3 |
4 | "Bot" is a word we use to describe software that sends and receives messages to present a user interface, rather than (or frequently, alongside) a traditional graphical UI. Many bots exist alongside real human users in chatrooms, and can take input in informal or "natural" language, which sometimes allows them to take the form of robotic coworkers or agents.
5 |
6 | Under their robotic skin, bots are actually connected web applications, and share many of the same components as websites or apps built for other platforms. Requests come in from users. The request is routed by software to the right content or function. A response is returned to the user.
7 |
8 | The goal of Botkit is to provide the core set of features and tools necessary to operate a bot on any messaging system. Bots are built by applying these features to specific tasks through a semantic, clearly documented programming library.
9 |
10 | Out of the box, Botkit bots include:
11 |
12 | * Conversation tracking and control
13 | * Event system
14 | * Platform connectors for popular messaging apps
15 | * Easy to extend plugin system
16 | * Integration with top NLP tools
17 | * Content management tools for dialog
18 | * Analytics
19 | * Self-contained Express webserver
20 |
--------------------------------------------------------------------------------
/readme.md:
--------------------------------------------------------------------------------
1 | # Legacy Botkit Documentation
2 |
3 | This project contains the LEGACY documentation for [Botkit v0.7 and before](https://github.com/howdyai/botkit/tree/legacy#tree) and is used to build [the official documentation site](https://botkit.ai/docs/v0)
4 |
5 | [Start here](docs/index.md)
6 |
--------------------------------------------------------------------------------
/todo.md:
--------------------------------------------------------------------------------
1 |
2 | * provisioning links
3 | * rename files readme-slack -> slack etc?
4 |
5 | # done
6 | * make a TOC
7 | * remove the boilerplate/toc from each of the docs
8 | * grep for any links directly to github or weird relative links
9 | * .md links get rewritten to .html even external so...
10 |
--------------------------------------------------------------------------------