@@ -56,23 +56,30 @@ Otherwise, follow [Botkit's instructions](https://botkit.ai/docs/provisioning/sl
5656This section walks you through code snippets to set up your Slack bot. If you want, you can jump straight to the [ full example] ( /examples/simple-bot ) .
5757
5858In your app, add the following lines to create your Slack controller using Botkit:
59- ``` js
60- const slackController = Botkit .slackbot ({ clientSigningSecret: YOUR_SLACK_SIGNING_SECRET });
61- ```
59+ ``` typescript
60+ import { WatsonMiddleware } from ' botkit-middleware-watson' ;
61+ import Botkit = require (' botkit' );
62+ const { SlackAdapter } = require (' botbuilder-adapter-slack' );
63+
64+ const adapter = new SlackAdapter ({
65+ clientSigningSecret: process .env .SLACK_SECRET ,
66+ botToken: process .env .SLACK_TOKEN
67+ });
6268
63- Spawn a Slack bot using the controller:
64- ``` js
65- const slackBot = slackController .spawn ({
66- token: YOUR_SLACK_TOKEN
69+ const controller = new Botkit ({
70+ adapter ,
71+ // ...other options
6772});
6873```
6974
75+
76+
7077Create the middleware object which you'll use to connect to the Watson Assistant service.
7178
7279If your credentials are ` username ` and ` password ` use:
7380
74- ``` js
75- const watsonMiddleware = require ( ' botkit-middleware-watson ' ) ({
81+ ``` typescript
82+ const watsonMiddleware = new WatsonMiddleware ({
7683 username: YOUR_ASSISTANT_USERNAME ,
7784 password: YOUR_ASSISTANT_PASSWORD ,
7885 url: YOUR_ASSISTANT_URL ,
@@ -84,8 +91,8 @@ const watsonMiddleware = require('botkit-middleware-watson')({
8491
8592If your credentials is ` apikey ` use:
8693
87- ``` js
88- const watsonMiddleware = require ( ' botkit-middleware-watson ' ) ({
94+ ``` typescript
95+ const watsonMiddleware = new WatsonMiddleware ({
8996 iam_apikey: YOUR_API_KEY ,
9097 url: YOUR_ASSISTANT_URL ,
9198 workspace_id: YOUR_WORKSPACE_ID ,
@@ -95,18 +102,17 @@ const watsonMiddleware = require('botkit-middleware-watson')({
95102```
96103
97104Tell your Slackbot to use the _ watsonMiddleware_ for incoming messages:
98- ``` js
99- slackController .middleware .receive .use (watsonMiddleware .receive );
100- slackBot .startRTM ();
105+ ``` typescript
106+ controller .middleware .receive .use (watsonMiddleware .receive .bind (watsonMiddleware ));
101107```
102108
103109Finally, make your bot _ listen_ to incoming messages and respond with Watson Assistant:
104- ``` js
105- slackController .hears ([' .*' ], [' direct_message' , ' direct_mention' , ' mention' ], function (bot , message ) {
110+ ``` typescript
111+ controller .hears ([' .*' ], [' direct_message' , ' direct_mention' , ' mention' ], async function (bot , message ) {
106112 if (message .watsonError ) {
107- bot .reply (message, " I'm sorry, but for technical reasons I can't respond to your message" );
113+ await bot .reply (message , " I'm sorry, but for technical reasons I can't respond to your message" );
108114 } else {
109- bot .reply (message, message .watsonData .output .text .join (' \n ' ));
115+ await bot .reply (message , message .watsonData .output .text .join (' \n ' ));
110116 }
111117});
112118```
@@ -125,7 +131,7 @@ If you would like to make your bot to only respond to _direct messages_ using As
125131#### Using interpret function instead of registering middleware
126132
127133``` js
128- slackController .hears ([' .*' ], [' direct_message' ], function (bot , message ) {
134+ slackController .hears ([' .*' ], [' direct_message' ], async function (bot , message ) {
129135 middleware .interpret (bot, message, function () {
130136 if (message .watsonError ) {
131137 bot .reply (message, " I'm sorry, but for technical reasons I can't respond to your message" );
@@ -158,16 +164,16 @@ To use the setup parameter `minimum_confidence`, you have multiple options:
158164
159165For example:
160166``` js
161- controller .hears ([' .*' ], [' direct_message' , ' direct_mention' , ' mention' , ' message_received' ], function (bot , message ) {
167+ controller .hears ([' .*' ], [' direct_message' , ' direct_mention' , ' mention' , ' message_received' ], async function (bot , message ) {
162168 if (message .watsonError ) {
163- bot .reply (message, " Sorry, there are technical problems." ); // deal with watson error
169+ await bot .reply (message, " Sorry, there are technical problems." ); // deal with watson error
164170 } else {
165171 if (message .watsonData .intents .length == 0 ) {
166- bot .reply (message, " Sorry, I could not understand the message." ); // was any intent recognized?
172+ await bot .reply (message, " Sorry, I could not understand the message." ); // was any intent recognized?
167173 } else if (message .watsonData .intents [0 ].confidence < watsonMiddleware .minimum_confidence ) {
168- bot .reply (message, " Sorry, I am not sure what you have said." ); // is the confidence high enough?
174+ await bot .reply (message, " Sorry, I am not sure what you have said." ); // is the confidence high enough?
169175 } else {
170- bot .reply (message, message .watsonData .output .text .join (' \n ' )); // reply with Watson response
176+ await bot .reply (message, message .watsonData .output .text .join (' \n ' )); // reply with Watson response
171177 }
172178 }
173179});
@@ -195,8 +201,8 @@ A common scenario of processing actions is:
195201### using sendToWatson to update context (possible since v1.5.0)
196202
197203Using sendToWatson to update context simplifies the bot code compared to solution using updateContext below.
198- ``` js
199204
205+ ``` typescript
200206function checkBalance(context , callback ) {
201207 // do something real here
202208 const contextDelta = {
@@ -208,127 +214,33 @@ function checkBalance(context, callback) {
208214
209215const checkBalanceAsync = Promise .promisify (checkBalance );
210216
211- const processWatsonResponse = function (bot , message ) {
212- if (message .watsonError ) {
213- return bot .reply (message, " I'm sorry, but for technical reasons I can't respond to your message" );
214- }
215- if (typeof message .watsonData .output !== ' undefined' ) {
216- // send "Please wait" to users
217- bot .reply (message, message .watsonData .output .text .join (' \n ' ));
218-
219- if (message .watsonData .output .action === ' check_balance' ) {
220- const newMessage = clone (message);
221- newMessage .text = ' balance result' ;
222-
223- checkBalanceAsync (message .watsonData .context ).then (function (contextDelta ) {
224- return watsonMiddleware .sendToWatsonAsync (bot, newMessage, contextDelta);
225- }).catch (function (error ) {
226- newMessage .watsonError = error;
227- }).then (function () {
228- return processWatsonResponse (bot, newMessage);
229- });
230- }
231- }
232- };
233-
234- controller .on (' message_received' , processWatsonResponse);
235- ```
236-
237- #### Using updateContext in controller (available since v1.4.0)
238-
239- Since 1.4.0 it is possible to update context from controller code.
240- ``` js
241-
242- function checkBalance (context , callback ) {
243- // this version of function updates only the context object
244- context .validAccount = true ;
245- context .accountBalance = 95.33 ;
246- callback (null , context);
247- }
248-
249- const checkBalanceAsync = Promise .promisify (checkBalance);
250-
251- const processWatsonResponse = function (bot , message ) {
217+ const processWatsonResponse = async (bot , message ) => {
252218 if (message .watsonError ) {
253- return bot .reply (message, " I'm sorry, but for technical reasons I can't respond to your message" );
219+ return await bot .reply (message , " I'm sorry, but for technical reasons I can't respond to your message" );
254220 }
255221 if (typeof message .watsonData .output !== ' undefined' ) {
256222 // send "Please wait" to users
257- bot .reply (message, message .watsonData .output .text .join (' \n ' ));
223+ await bot .reply (message , message .watsonData .output .text .join (' \n ' ));
258224
259225 if (message .watsonData .output .action === ' check_balance' ) {
260226 const newMessage = clone (message );
261227 newMessage .text = ' balance result' ;
262228
263- // check balance
264- checkBalanceAsync (message .watsonData .context ).then (function (context ) {
265- // update context in storage
266- return watsonMiddleware .updateContextAsync (message .user , context);
267- }).then (function () {
268- // send message to watson (it reads updated context from storage)
269- return watsonMiddleware .sendToWatsonAsync (bot, newMessage);
270- }).catch (function (error ) {
229+ try {
230+ const contextDelta = await checkBalanceAsync (message .watsonData .context );
231+ await watsonMiddleware .sendToWatsonAsync (bot , newMessage , contextDelta );
232+ }catch (error ) {
271233 newMessage .watsonError = error ;
272- }).then (function () {
273- // send results to user
274- return processWatsonResponse (bot, newMessage);
275- });
276- }
277- }
278- };
279-
280- controller .on (' message_received' , processWatsonResponse);
281- ```
282-
283- #### Using middleware.after and controller
284-
285- Before v1.4.0 only middleware.after callback can update context, and only controller can send replies to user.
286- The downside is that it is impossible to send "Please wait message".
287-
288- ``` js
289- function checkBalance (watsonResponse , callback ) {
290- // middleware.after function must pass a complete Watson respose to callback
291- watsonResponse .context .validAccount = true ;
292- watsonResponse .context .accountBalance = 95.33 ;
293- callback (null , watsonResponse);
294- }
295-
296- watsonMiddleware .after = function (message , watsonResponse , callback ) {
297- // real action happens in middleware.after
298- if (typeof watsonResponse !== ' undefined' && typeof watsonResponse .output !== ' undefined' ) {
299- if (watsonResponse .output .action === ' check_balance' ) {
300- return checkBalance (watsonResponse, callback);
301- }
302- }
303- callback (null , watsonResponse);
304- };
305-
306- const processWatsonResponse = function (bot , message ) {
307- if (message .watsonError ) {
308- return bot .reply (message, " I'm sorry, but for technical reasons I can't respond to your message" );
309- }
310-
311- if (typeof message .watsonData .output !== ' undefined' ) {
312- // send "Please wait" to users
313- bot .reply (message, message .watsonData .output .text .join (' \n ' ));
314-
315- if (message .watsonData .output .action === ' check_balance' ) {
316- const newMessage = clone (message);
317- newMessage .text = ' balance result' ;
318- // send to watson
319- watsonMiddleware .interpret (bot, newMessage, function () {
320- // send results to user
321- processWatsonResponse (bot, newMessage);
322- });
234+ }
235+
236+ return await processWatsonResponse (bot , newMessage );
323237 }
324238 }
325239};
326240
327241controller .on (' message_received' , processWatsonResponse );
328-
329242```
330243
331-
332244## Implementing event handlers
333245
334246Events are messages having type different than ` message ` .
@@ -376,17 +288,17 @@ The `hear()` function can be used on individual handler functions, or can be use
376288
377289Used on an individual handler:
378290
379- ``` js
380- slackController .hears ([' hello' ], [' direct_message' , ' direct_mention' , ' mention' ], watsonMiddleware .hear , function (bot , message ) {
381- bot .reply (message, message .watsonData .output .text .join (' \n ' ));
291+ ``` typescript
292+ slackController .hears ([' hello' ], [' direct_message' , ' direct_mention' , ' mention' ], watsonMiddleware .hear , async function (bot , message ) {
293+ await bot .reply (message , message .watsonData .output .text .join (' \n ' ));
382294 // now do something special related to the hello intent
383295});
384296```
385297
386298Used globally:
387299
388- ``` js
389- slackController .changeEars (watsonMiddleware .hear );
300+ ``` typescript
301+ slackController .changeEars (watsonMiddleware .hear . bind ( watsonMiddleware ) );
390302
391303slackController .hears ([' hello' ], [' direct_message' , ' direct_mention' , ' mention' ], function (bot , message ) {
392304 bot .reply (message , message .watsonData .output .text .join (' \n ' ));
@@ -419,20 +331,21 @@ middleware.before = function(message, assistantPayload, callback) {
419331If you need to make use of multiple workspaces in a single bot, workspace_id can be changed dynamically by setting workspace_id property in context.
420332
421333Example of setting workspace_id to id provided as a property of hello message:
422- ``` js
423- function handleHelloEvent (bot , message ) {
424- message .type = ' welcome' ;
425- const contextDelta = {};
334+ ``` typescript
335+ async function handleHelloEvent(bot , message ) {
336+ message .type = ' welcome' ;
337+ const contextDelta = {};
426338
427- if (message .workspaceId ) {
428- contextDelta .workspace_id = message .workspaceId ;
429- }
339+ if (message .workspaceId ) {
340+ contextDelta .workspace_id = message .workspaceId ;
341+ }
430342
431- watsonMiddleware .sendToWatsonAsync (bot, message, contextDelta).catch (function (error ) {
432- message .watsonError = error;
433- }).then (function () {
434- bot .reply (message, message .watsonData .output .text .join (' \n ' ));
435- });
343+ try {
344+ watsonMiddleware .sendToWatsonAsync (bot , message , contextDelta );
345+ } catch (error ) {
346+ message .watsonError = error ;
347+ }
348+ await bot .reply (message , message .watsonData .output .text .join (' \n ' ));
436349}
437350
438351controller .on (' hello' , handleHelloEvent );
0 commit comments