Search code examples
javascriptbotframeworkweb-chat

BotFramework Webchat v4 Sending message back through the javascript


I need help using the webchat v4 from BotFramework from Microsoft to send a message back to the bot through the Javascript.

My bot code is written in C# (.NET Framework) but at some point in my scenario I need to trigger some javascript to ask for the location from the user. What do I do?

  1. I send an activity of type event
  2. In the store from the bot, I catch the said activity (here is my code):
const store = window.WebChat.createStore({},
    ({ dispatch }) => next => action => {
        //console.log('action of type ' + action.type);

        if (action.type === 'DIRECT_LINE/INCOMING_ACTIVITY') {
            var activityOut = action.payload.activity;

            if (activityOut.type === 'message') {
                // Store message

                return next(action);
            }

            if (activityOut.type === 'event') {
                // Handle based on event type
                if (activityOut.name === 'getLocation') {
                    if (navigator.geolocation)
                    {
                        navigator.geolocation.getCurrentPosition(showPosition);
                    }
                    else
                    { 
                        console.log("Geolocation is not supported by this browser.");
                    }
                } else {
                    return next(action);
                }
            }
        }
        else if (action.type === 'DIRECT_LINE/POST_ACTIVITY') {
            var activityIn = action.payload.activity;

            if (activityIn.type === 'message') {
                // Store message
            }

            return next(action);
        }
        else {
            return next(action);
        }
    });
  1. I send the information to the bot (here the location):
function showPosition(position) {
    console.log("Latitude: " + position.coords.latitude + " Longitude: " + position.coords.longitude);

    var v = position.coords.latitude +';' + position.coords.longitude;
    store.dispatch({
        type: 'WEB_CHAT/SEND_MESSAGE_BACK',
        payload:
        {
            text: v,
            value : v
        }
    });
}

I also tried with 'WEB_CHAT/SEND_MESSAGE' but it doesn't change anything.

For more information, here is my piece of code to connect to the bot:

window.WebChat.renderWebChat(
            {
                directLine: window.WebChat.createDirectLine({
                    secret: 'my secret (will change to a token of course)'
                }),
                store,
                userID: chatUser.id,
                username: chatUser.name,
                locale: 'fr-FR',
                styleOptions
            },
            document.getElementById('BotChatGoesHere')
        );

Here is the exception I get whenever I'm doing this: Console error Activity send

Thank you already for anyone that will help me!


Solution

  • I think you are ever so slightly over-engineering the code. All you need to do is filter on the incoming event and then call your function. See the example below.

    dialog.js (Node bot example): Sending a simple event as a waterfall step. The 'name' property that I will be filtering on is assigned to channelData.

    async eventStep ( stepContext ) {
      let reply = { type: ActivityTypes.Event };
      reply.channelData = { name: 'getLocation' };
    
      await stepContext.context.sendActivities( reply );
      return await stepContext.next();
    }
    

    createStore(): I filter on the event type of the incoming activities. If the channelData property includes name with the correct value, then the showPosition function is called.

    const store = window.WebChat.createStore( {}, ( { dispatch } ) => next => async action => {
      if (action.type === 'DIRECT_LINE/INCOMING_ACTIVITY') {
        const { activity } = action.payload;
    
        if ( activity.type === 'event' ) {
          // Handle based on event type
          if ( activity.channelData.name === 'getLocation' ) {
            if ( navigator.geolocation ) {
              await navigator.geolocation.getCurrentPosition( showPosition );
            }
            else {
              console.log( "Geolocation is not supported by this browser." );
            }
          }
        }
      }
    
      return next(action);
    });
    

    showPosition(): I have the function positioned just after the Web Chat renderer. I also demonstrate sending SEND_MESSAGE, SEND_MESSAGE_BACK, SEND_POST_BACK, and SEND_EVENT. How the data is arranged in the activity is different in each case. See below.

      [...]
    
      document.getElementById('BotChatGoesHere')
    );
    
    function showPosition( position ) {
      const message = "Latitude: " + position.coords.latitude + " Longitude: " + position.coords.longitude;
    
      store.dispatch( {
        type: 'WEB_CHAT/SEND_MESSAGE',
        payload:
          {
            text: message,
            channelData: { latitude: position.coords.latitude, longitude: position.coords.longitude }
          }
      } );
    
      store.dispatch( {
        type: 'WEB_CHAT/SEND_MESSAGE_BACK',
        payload:
          {
            text: message,
            value: { latitude: position.coords.latitude, longitude: position.coords.longitude }
          }
      } );
    
      store.dispatch( {
        type: 'WEB_CHAT/SEND_POST_BACK',
        payload: { value: { latitude: position.coords.latitude, longitude: position.coords.longitude } }
      } );
    
      store.dispatch( {
        type: 'WEB_CHAT/SEND_EVENT',
        payload:
          {
            name: 'EVENT_GET_POSITION',
            value: { latitude: position.coords.latitude, longitude: position.coords.longitude }
          }
      } );
    }
    

    SEND_MESSAGE: Sends as a message; has text field; displays to the user; data in activity.channelData

    enter image description here

    SEND_MESSAGE_BACK: Sends as a message; has text field; DOES NOT display to the user; data in activity.value

    enter image description here

    SEND_POST_BACK: Sends as a message; has NO text field; DOES NOT display to the user; data in activity.value

    enter image description here

    SEND_EVENT: Sends as an event; has NO text field; DOES NOT display to the user; event name in activity.name and data in activity.value

    enter image description here

    Hope of help!