Microsoft BotFramework-WebChat is getting two welcome messages - botframework

I am using code based on https://github.com/Microsoft/BotFramework-WebChat/blob/master/samples/15.d.backchannel-send-welcome-event/index.html
When I load the web page I get two of the welcome messages. Looking at the console output of my bot I can see two conversation updates happening.
This doesn't happen with the Bot framework emulator, which only shows one welcome message.
The only place where my code differs from the sample is in rendering:
window.WebChat.renderWebChat({
directLine: window.WebChat.createDirectLine({ token }),
store,
styleOptions,
userID: guid(),
}, document.getElementById('webchat'));
Why is this hapening? Why is the web channel sending two "join" events for the user?
My code handling conversation updates looks like this:
} else if (turnContext.activity.type === ActivityTypes.ConversationUpdate) {
if (DEBUG) { console.log("ConversationUpdate"); }
// Do we have any new members added to the conversation?
if (turnContext.activity.membersAdded.length !== 0) {
// Iterate over all new members added to the conversation
for (var idx in turnContext.activity.membersAdded) {
console.log(turnContext.activity.membersAdded);
// Greet anyone that was not the target (recipient) of this message
// the 'bot' is the recipient for events from the channel,
// turnContext.activity.membersAdded == turnContext.activity.recipient.Id indicates the
// bot was added to the conversation.
if (turnContext.activity.membersAdded[idx].id != turnContext.activity.recipient.id) {
if (DEBUG) {console.log("Starting MASTER_DIALOG");}
const user = await this.userProfile.get(turnContext, {});
user.id = this.guid();
await this.userProfile.set(turnContext, user);
await this.userState.saveChanges(turnContext);
return await dialogContext.beginDialog(MASTER_DIALOG)
}
}
}
}

Using the ConversationUpdate event for sending a welcome message is not recommended. Read more about how to properly send a greeting message.
There will be two ConversationUpdate events per connection. One for when bot joins the conversation and one for when a (human) user joins the conversation. In your current code you are iterating over all new members, where you have to filter out the bot itself.
A better option would be to make use of a custom event sent using the backchannel. In the example you mention, you already have this functionality. It will sent a new event webchat/join to your bot, which even includes the browser language by default.

Related

What's the right way to handle message reactions in a notification only bot?

I have created a one way notification only bot in Teams (only personal scope), I am able to send proactive messages but however, when someone reacts to a message, Teams is showing a notification for the message which was reacted to. How do I prevent this behavior and just silently ignore the message reaction. I was hoping since it's a one way notification bot, there would be an option to disable it, but apparently there isn't.
I have a PHP REST API endpoint which is configured to be the bot endpoint address. This API is pretty basic and handles only certain types of requests like installationUpdate. For all other types, it just sends a HTTP 200 response with an empty body.
When the user first installs the App in teams, I am storing the conversationId, tenantId and the serviceUrl and later use these values to send notifications (proactive messages) when certain events happen in a web application. These are sent via a C# Console Application.
When a user reacts to a message, I get a request with the type messageReaction, this is where I am unable to figure out how to handle this so that the message reaction is ignored and does not cause a notification in Teams.
This is what my PHP REST API (bot endpoint) looks like
function onBotRequest() {
if ($_SERVER['REQUEST_METHOD'] != 'POST') {
http_response_code(404);
return;
}
$requestJson = json_decode(file_get_contents('php://input'), true);
if ($requestJson['channelId'] != 'msteams') {
http_response_code(404);
return;
} elseif ($requestJson['type'] == 'installationUpdate') {
$serviceUrl = $requestJson["serviceUrl"];
$conversationId = $requestJson["conversation"]["id"];
$tenantId = $requestJson["conversation"]["tenantId"];
if ($requestJson['action'] == 'add') {
// App installed
// Store conversationId, tenantId, serviceUrl in db
} elseif($requestJson['action'] == 'remove') {
// App uninstalled
// Remove conversationId, tenantId, serviceUrl from db
}
} elseif ($requestJson['type'] == 'messageReaction') {
// What should be sent as the response here to ignore the message reaction?
}
header('Content-Type: application/json');
http_response_code(200);
}
The code used for sending proactive messages
var credentials = new MicrosoftAppCredentials(appId, appPassword);
var connectorClient = new ConnectorClient(new Uri(serviceUrl), credentials);
var response = await connectorClient.Conversations.SendToConversationAsync(conversationId, activity);
I tried sending different HTTP status codes like 400 but irrespective of the response status code, the notification still occurs. I guess I am missing some required params in the response body, but I couldn't find any documentation.
Removing the call to TeamsNotifyUser will prevent Teams sending notifications when message reactions are added/removed.

How to implement a welcome activity when the bot first starts - NLP is from Google Dialogflow

How to implement a welcome activity when the bot first starts - NLP is from Google Dialogflow.
I have designed the chatbot -intent, entities and NLP from Google Dialogflow and I have integrated successfully with the botframework webchat in a html file on referring this url.
The bot design and also the bot response is good to go. My most expected is am not getting the Bot response first here.
The welcome intent from Google Dialogflow has to get trigger from the following code as per the link given above.
But I am unable to get the bot trigger first here.
How to trigger the event of Google Dialogflow from the code.
I am expecting same like this
Note: Also referred this url
When a user joins WebChat, a conversation update activity will be sent to the bot. Once the activity is received, you can check if a member was added and send the welcome message accordingly.
If you are using the Activity Handler that was released in v4.3, you can simply add an onMembersAdded handler and send the welcome message from there.
class Bot extends ActivityHandler{
constructor() {
super();
this.onMembersAdded(async (context, next) => {
const { membersAdded } = context.activity;
for (let member of membersAdded) {
if (member.id !== context.activity.recipient.id) {
await context.sendActivity("Welcome Message!");
}
}
await next();
});
...
}
}
If you are not using the activity handler, in the bot's onTurn method, you can check if the incoming activity handler is a conversation update and if a member has been added.
async onTurn(turnContext) {
if (turnContext.activity.type === ActivityTypes.ConversationUpdate) {
if (turnContext.activity.membersAdded && turnContext.activity.membersAdded.length > 0) {
for (let member of turnContext.activity.membersAdded) {
if (member.id !== turnContext.activity.recipient.id) {
await turnContext.sendActivity("Welcome Message!");
}
}
}
} ...
}
For more details on sending welcome messages, please take a look at this sample.
Hope this helps!

Is there a way to read all the messages which are already posted in the bot without knowing their respective Conversation IDs

I am using directline V3 for testing out a bot inside MS Teams.
This is a bot showing some messages inside MS Teams.
Is there a way to read all the messages which are already posted in the bot without knowing their respective Conversation IDs. How to read all the conversations from the bot show in the attached screenshot.
On bot side, if we want to save and retrieve all the conversation history, in C# we can implement the IActivityLogger interface, and log the data in Task LogAsync(IActivity activity) for example:
public class ActivityLogger : IActivityLogger
{
public Task LogAsync(IActivity activity)
{
IMessageActivity msg = activity.AsMessageActivity();
//log here
return null;
}
}
So if you save data in Azure SQL Database, you can refer to Saving Bot Activities in Azure SQL Database, and here are some official examples.
Then in node.js, you can intercept and log messages using middleware:
bot.use({
botbuilder: function (session, next) {
myMiddleware.logIncomingMessage(session, next);
},
send: function (event, next) {
myMiddleware.logOutgoingMessage(event, next);
}
})

Get conversation ID in directline bot framework inline

I am using directline for webchat.
I want to include a refresh button on top of the chat and for that I need the conversation ID. How can I get the ID? Is it possible by using inline webchat ?
This the refresh button that I am trying to implement
I was facing the same problem, as I wanted to pass the conversation ID to my custom controller for initial authentication and correspondingly, push a custom auth data to the conversation stack of the bot framework relating to that specific conversation ID.
My hunting got me to this issue post on Github:
In the 3rd post by inmarktech he mentions the below code:
var params = BotChat.queryParams(location.search);
var my_token = params['my_token'];
var botConnection = new BotChat.DirectLine({
secret: 'DIRECTLINE_SECRET'
});
BotChat.App({
botConnection: botConnection
,user: { id: 'USER_ID', name: 'User' } // user.id auto updates after first user message
}, document.getElementById("bot"));
botConnection.connectionStatus$.subscribe(function (status) {
if (status == 2) { // wait for connection is 'OnLine' to send data to bot
var convID = botConnection.conversationId;
botConnection.postActivity({
from: { id: convID } // because first time user ID == conversation ID
,type: 'event'
,name: 'registerUserData' // event name as we need
,value: my_token // data attached to event
}).subscribe(function (activityId) {
// This subscription is a MUST
// If I remove this handler the postActivity not reaches the bot
});
}
});
as you can see he is subscribing to botConnection.connectionStatus$ and as and when the status property is equal to 2(Online) you can then fetch the Conversation ID from the botConnection object.
Hope that helps :)

Is it possible to detect when a user opens the chat window on Facebook?

I'm trying to create a chatbot where in order to avoid the user opening the chat window and not knowing the available options, I want to give some basic instructions when the user opens the chat window.
Is there any trigger available when the user opens a chat window? Maybe then I can check, and if there's not an ongoing conversation I could provide basic instructions.
I did some googling and found nothing about this. Is it possible to do something like this, and if not, is there a way to mitigate this problem, and provide the user with information regarding the chatbot capabilities and supported instructions?
Facebook does not allow bots to initiate a conversation, unlike Skype or other platforms.
There are still some tricks you can do :
Go on the Settings of your Facebook page, then Messaging and check "Show a Messenger Greeting" as below, and write your greeting sentence.
The result will look like this :
You can also set a "Get Started" button to trigger an event.
Here's the doc :
"https://developers.facebook.com/docs/messenger-platform/thread-settings/get-started-button"
You can monitor for two event types: ConversationUpdate and ContactRelationUpdate.
The first one (ConversationUpdate) is called when a user is added or removed from the conversation. So, there's a place where you can introduce available options. It will be each type the new conversation has started. So, it may become annoying, you may add a check - do not show it if the user has been using the bot for some time.
The second (ContactRelationUpdate) is called when a user adds or removes the bot to/from the contacts. In general, it is only called once per user action.
Here's the extract from the Bot-Frameworks examples:
For Node.Js
bot.on('conversationUpdate', function (message) {
// Check for group conversations
if (message.address.conversation.isGroup) {
// Send a hello message when bot is added
if (message.membersAdded) {
message.membersAdded.forEach(function (identity) {
if (identity.id === message.address.bot.id) {
var reply = new builder.Message()
.address(message.address)
.text("Hello everyone!");
bot.send(reply);
}
});
}
// Send a goodbye message when bot is removed
if (message.membersRemoved) {
message.membersRemoved.forEach(function (identity) {
if (identity.id === message.address.bot.id) {
var reply = new builder.Message()
.address(message.address)
.text("Goodbye");
bot.send(reply);
}
});
}
}
});
bot.on('contactRelationUpdate', function (message) {
if (message.action === 'add') {
var name = message.user ? message.user.name : null;
var reply = new builder.Message()
.address(message.address)
.text("Hello %s... Thanks for adding me. Say 'hello' to see some great demos.", name || 'there');
bot.send(reply);
} else {
// delete their data
}
});
For C#
private void HandleMessage(Activity message)
{
if (message.Type == ActivityTypes.ConversationUpdate)
{
if (activity.MembersAdded.Any(m => m.Id == activity.Recipient.Id))
{
var connector = new ConnectorClient(new Uri(activity.ServiceUrl));
var response = activity.CreateReply();
response.Text = "Hi! I am Bot. Here's what you can do...";
await connector.Conversations.ReplyToActivityAsync(response);
}
}
else if (message.Type == ActivityTypes.ContactRelationUpdate)
{
if (Activity.AsContactRelationUpdateActivity().Action == ContactRelationUpdateActionTypes.Add)
{
var connector = new ConnectorClient(new Uri(activity.ServiceUrl));
var response = activity.CreateReply();
response.Text = "Hi! I am Bot. Thanks for adding me. Here's what you can do...";
}
}
return null;
}
I think the acid answer is not.
But you can intercept the IConversationUpdateActivity type message to know if the user has added the bot to a conversation. In the C# project template you can find a code block that ask for this message type but do nothing.

Resources