├── .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 | [![Remix on Glitch](glitch.png)](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 | ![Screenshot of the 'Add a bot' flow in Webex developer portal](IMG/cisco_add.png) 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 | ![Screenshot of create an APP ID in Facebook developer portal](IMG/fb_new.png) 18 | 19 | * Select a Messenger application 20 | 21 | ![Screenshot of configuring your app in the Facebook developer portal](IMG/fb_mess.png) 22 | 23 | ### 3. Get a Page Access Token for your app 24 | Scroll down to `Token Generation` 25 | 26 | ![Screenshot of page access tokens in Facebook portal](IMG/fb_tokengen.png) 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 | ![Screenshot of configuring webhooks in the Facebook portal](IMG/fb_webhooks.png) 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 | ![Create your app](IMG/slack-new.png) 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 | ![A screenshot of the "Create your app" modal on Slack's API portal](IMG/slack_client_secret.png) 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 | ![A screenshot of the "Setup Oauth" tab on Slack's portal](IMG/slack_oauth.png) 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 | ![A screenshot of the "Bot User" screen on Slack's portal](IMG/slack-botuser.png) 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 | ![A screeshot showing how to setup interactive components](IMG/slack-im.png) 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 | ![A screenshot showing how to set up webhook endpoints](IMG/Slack-eventsenable.png) 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 | ![A screenshot showing how to add message subscriptions](IMG/slack_botevents.png) 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 |
86 | 87 | 88 |
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 |
133 |
134 | 135 | 136 |
137 |
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 |
181 |
182 | 183 | 184 |
185 |
186 |
187 |
188 |
189 |
190 | 191 | 192 |
193 |
194 |
195 |
196 |
197 |
198 | 199 | 200 |
201 |
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 |
220 |
221 | 222 |
223 | 224 |
225 |
226 |
227 | 228 |
229 | 234 |
235 |
236 |
237 | 238 |
239 | 241 | 243 | 245 |
246 |
247 |
248 | 249 |
250 |