BotFramework conversation not found - azure

I've been trying to test a function app sending an activity to a bot that has an existing conversation, but to simplify for this post, I'll speak in terms of sending it via postman. I've have been butting up against an issue wherein the conversationId is not being found, despite confirming it does exist beforehand and I'm not entirely sure what I've done wrong.
I log onto portal azure, and go to my bot to Test in Web Chat. I authenticate the bot, and the conversation starts.
Here, I've checked the conversationId is exactly what I expect to be by examining the conversation calls response in Chromes debug tools, in this case it is 1GJ0N9UYKGyELu3LqpDF6b-a
Here is the exact conversation response...
conversationId: "1GJ0N9UYKGyELu3LqpDF6b-a"
expires_in: 3600
referenceGrammarId: "fcab5fbf-67c7-bf55-934a-274e525c78a9"
streamUrl: "wss://webchat.botframework.com/v3/directline/conversations/1GJ0N9UYKGyELu3LqpDF6b-a/stream?watermark=-&t=ew0KICAi...."
token: "ew0KICA..."
So from here, in my mind I should be able to do the following in postman
POST https://webchat.botframework.com/v3/directline/conversations/1GJ0N9UYKGyELu3LqpDF6b-a/activities
Content-Type: application/json
Authorization: Bearer {My webchats channels secret code}
Body:
{
"type": "message",
"from": {
"name": "foo"
},
"text": "bar"
}
I'd expect a 200OK and the message 'bar' to appear in my Test In Web Chat from 'foo', but it does not. Instead I get an error in postman stating:
{
"error": {
"code": "BadArgument",
"message": "Conversation not found"
}
}
How exactly can this be? If I've just created that conversation and can demonstrate that conversationId is in use, why is the post message saying it can't be found? Am I incorrectly using channels? Or doing something blindingly obvious here?

So to answer my own question, to make a long story short. It looks like the example activity supplied in the Microsoft documentation doesn't quite cut it. There is something else that is required, although I didn't have time to narrow it down.
The solution I took, as I was running low on time was to write a method to save an activity to cosmosDb as part of the authentication flow. This way I have an ironclad activity that I know has worked in at least the invoke stages of the dialog, and I know a conversation reference is correct and present. From there I pulled the activity and changed 4 fields in it.
activity.Type = "message",
activity.From = new From { Id = "{BotId}", Name = "Gilbert Bottfried", Role = "bot },
activity.Text = "{My message}",
activity.Subject = "{my message subject}"
From there, it was essentially a case of just creating a connector client and firing off this repurposed activity.
AppCredentials.TrustServiceUrl(serviceUrl, DateTime.MaxValue);
ConnectorClient client = new ConnectorClient(
new Uri(serviceUrl),
MicrosoftAppId,
MicrosoftAppPassword);
await client.Conversations.SendToConversationAsync(activity.Conversation.Id, activity);
It seems that this was enough to get it working, and it makes for a nice referenceable conversation Id for future messages. Although I found other issues with working with WebChat, because I suspect it's not entirely stable sending messages to and throw via websockets. The testing experience was much more stable on msteams itself, it seemed to handle my barrage of test messages like a champ.
This is essentially a bruteforce method, as I'm storing and sending a lot of unnecessary data, but it works. I may append this answer to trim down what I find to be necessary in the future, but that will require testing.

Related

Proactive messaging bot in Teams without mentioning the bot beforehand

I'm using the Microsoft bot-framework to create a bot and integrate it into teams.
Part of the bot's requirements include proactively messaging users once per day. From what I understand, I can only message users that has been added to the team/groupChat after the bot, or that have messaged the bot directly.
My question is - can I somehow bypass this limitation?
A friend of my referred me to a new feature of graphAPI, as part of the new beta version - https://learn.microsoft.com/en-us/graph/api/user-add-teamsappinstallation?view=graph-rest-beta&tabs=http.
To me it doesn't seem like it could be related to the solution since I'm not getting any data back in the response, so if I have no conversationReference object I still can't message the user.
At the moment my solution is to simply broadcast a message in the channel when it's added, asking users to "register" with it by messaging it. Anyone has any other suggestion?
The easiest way is to:
Install the bot for the team
Query the Team Roster -- The link in Step 3 has an alternative way to do this towards the bottom
Create a conversation with the user and send a proactive message
There's a lot of code in those links and it's better to just visit them than to copy/paste it here.
The end of Step 3 also mentions trustServiceUrl, which you may find handy if you run into permissions/auth issues when trying to send a proactive message.
Edit for Node:
Install Necessary Packages
npm i -S npm install botbuilder-teams#4.0.0-beta1 botframework-connector
Note: The #<version> is important!
Prepare the Adapter
In index.js
const teams = require('botbuilder-teams');
adapter.use(new teams.TeamsMiddleware());
Get the Roster
// Get Team Roster
const credentials = new MicrosoftAppCredentials(process.env.MicrosoftAppId, process.env.MicrosoftAppPassword);
const connector = new ConnectorClient(credentials, { baseUri: context.activity.serviceUrl });
const roster = await connector.conversations.getConversationMembers(context.activity.conversation.id);
Send the Proactive Message
const { TeamsContext } = require('botbuilder-teams');
// Send Proactive Message
const teamsCtx = TeamsContext.from(context);
const parameters = {
members: [
roster[0] // Replace with appropriate user
],
channelData: {
tenant: {
id: teamsCtx.tenant.id
}
}
};
const conversationResource = await connector.conversations.createConversation(parameters);
const message = MessageFactory.text('This is a proactive message');
await connector.conversations.sendToConversation(conversationResource.id, message);
Trust the ServiceUrl, as Necessary
Read about it. You'd want this before the message is sent.
MicrosoftAppCredentials.trustServiceUrl(context.activity.serviceUrl);
EDIT: The Graph API you've referenced is only necessary if you wish to proactively message a user who is not in a channel/groupChat where the bot is installed. If you need to proactively message only people who are in context where the bot is installed already, the answer from mdrichardson is the easiest possible method.
We've identified a couple of issues with the Graph API beta endpoint you referenced that should be fixed in the near term. In the meantime workarounds are as follows:
Calling:
POST https://graph.microsoft.com/beta/me/teamwork/installedApps/
{"teamsapp#odata.bind":"https://graph.microsoft.com/beta/appcatalogs/teamsapps/APP-GUID"}
Will install an app in the personal scope of a user.
Known issue: Currently, if the app contains a bot, then installation will not lead to creation of thread between the bot and the user. However to ensure that any missing chat threads, get created, call:
GET https://graph.microsoft.com/beta/me/chats?$filter=installedApps/any(x:x/teamsApp/id eq 'APP-GUID')
Calling:
GET https://graph.microsoft.com/beta/me/chats?$filter=installedApps/any(x:x/teamsApp/id eq 'APP-GUID')
Gets the chat between a user and an app containing a bot.
Known issue: Calling this API will lead to sending a conversation update event to the bot even though there were no updates to the conversation. Your bot will essentially get two install events and you'll need to make sure you don't send the welcome message twice.
We'll also be adding more detailed documentation for the proactive messaging flow using these Graph APIs

Microsoft Teams outgoing webhooks broken?

I am developing an integration in Teams using outgoing webhooks and it was working fine until recently, but now, my webhook keeps replying there is an error with my request (Sorry, there was a problem encountered with your request)
I had this problem at first, but I solved it by having my service send the correct reply following the doc (https://learn.microsoft.com/en-us/microsoftteams/platform/concepts/outgoingwebhook)
Something like :
{
"type": "message",
"text": "This is a reply!"
}
But now, I always get an error response, even though my service is replying with the supposedly correct json.
It looks like something changed in the implementation, but the documentation is not up to date
Any help would be appreciated.
Thanks!

Directline API message to Microsoft Bot

I have created the bot in azure services using LUIS, which used as chatbot and can create conversations using dialogs.
At some point, I am trying to push messages to chatbot using Direct Line API 3.0, I'm using Postman to send the messages to bot.
I followed the instructions from this page, https://learn.microsoft.com/en-us/azure/bot-service/rest-api/bot-framework-rest-direct-line-3-0-send-activity?view=azure-bot-service-4.0
I'm able to send message to the conversation as bot, below is the image I sent message from Postman and got successful response.
But my issue is, after the message is sent, the bot tries to analyse even though it's not user message. Bot starts to send message from default message handler like below,
Even after sending the message successfully, my bot triggers the default message handler, which is expected only to happen for user messages but not for bot messages.
Also, I have checked with webchat channel, which it doesn't trigger this default message handler. This is happening only in DirectLine API, can anyone help me on this.
Instead of sending the message as type "message", you should send it as "event".
This way your MessagesController will see it as an ActivityType of Event instead of Message and you can process however you want without spaghettifying your actual message handling
If you want to send different kinds of event to make it even easier, then you can 'name' you event by supplying the 'name' field with a value in your json.
Third, if you need to include data with the message, you would supply a value in the 'value' field of your json.
The github page for the standard webchat client has some great information on sending events. It might shed a bit more light on the json.
You can read more about the 'event' activity type here
You message json would look something more like this:
{
"type": "event",
"from": {
"id": "user1"
},
"name": "theEvent",
"value": "someDataMyBotNeeds"
}

Posting on facebook via unificationengine

Hi I'd like to post to facebook via unification engine. I've already created a user, added and tested successfully a facebook connection, but when I post I get the following response:
{"Status":{"facebook":{"status":190,"info":"Error validating access token: Session does not match current stored session. This may be because the user changed the password since the time the session was created or Facebook has changed the session for security reasons.: "}},"URIs":[]}
When I use the facebook token, that was used for creating the connection, to post to facebook directly (without unificationengine), then it works just fine. What might be the problem here? Status 190 is neither documented on facebook nor on unificationengine.
#unificatinengine developers: it would be practical, if the errors returned by the service would be passed on inside the unificationengine response, this way debugging such errors would be easier, and the errors could also be processed programmatically.
Additional info
Today I seem not to be able to reproduce the response of yesterday. The postfields I use to post the message to facebook (the same as yesterday) are as follows:
{
"message":{
"receivers":[
{
"name":"me",
"address":"https://graph.facebook.com/v2.1/me/feed",
"Connector":"facebook"
}
],
"sender":{
"address":"sender address"
},
"subject":"test",
"parts":[
{
"id":"0",
"contentType":"text/plain",
"type":"body",
"size":25,
"data":"this is the plain message"
},
{
"id":"1",
"contentType":"text/html",
"type":"body",
"size":42,
"data":"<div>this is the <b>html</b> message</div>"
},
{
"id":"2",
"contentType":"text/plain",
"type":"link",
"size":17,
"data":"http://www.web.de"
},
{
"id":"3",
"contentType":"text/plain",
"type":"link_description",
"size":21,
"data":"some link description"
},
{
"id":"4",
"contentType":"text/plain",
"type":"link_title",
"size":10,
"data":"link title"
}
]
}
}
But today I get the following message back from unificationengine
{
"Status":{
"facebook":{
"status":100,
"info":"Unsupported post request. Please read the Graph API documentation at https://developers.facebook.com/docs/graph-api: "
}
},
"URIs":[]
}
Unfortunately this does not tell me, what unificationengine does internally for posting to facebook (which should not concern me), and what goes wrong there.
Does the "/v2/connection/info" show the details of the facebook connection that you have added? If not can you please update the connection with a new access token, using the same connection identifier for the "v2/connection/add" api endpoint, and check if it works.
unificationengine

AuthorizationError when confirming SNS subscription over HTTP

I'm writing a simple SNS client that is meant to subscribe itself to an SNS topic and then listen for notifications. I can successfully submit a sns.subscribe request, but when I pick up the SubscriptionConfirmation POST message from AWS and try and respond using sns.confirmSubscription I get an AuthorizationError returned:
[AuthorizationError: User: arn:aws:iam::xxx:user/mv-user is not authorized to perform: SNS:ConfirmSubscription on resource: arn:aws:sns:us-east-1:xxx:*]
If I use exactly the same Token and TopicArn in a GET query to the server the subscription confirmation works fine, with no authentication.
Any ideas why it's not working? My SNS topic is wide open with publish/subscribe permissions set to 'Everyone'.
For reference, my code is something like this:
var params = {
TopicArn: topicArn, // e.g. arn:aws:sns:us-east-1:xxx:yyy
Token: token // long token extracted from POST body
};
sns.confirmSubscription(params, function (err, data) {
if (err) {
// BOOOM - keep getting here with AuthorizationError
} else {
// Yay. Worked, but never seem to get here :(
}
});
However, if I navigate to the URL similar to this in a browser (i.e. completely unauthenticated), it works perfectly:
http://sns.us-east-1.amazonaws.com/?Action=ConfirmSubscription&Token=<token>&TopicArn=arn%3Aaws%3Asns%3Aus-east-1%3Axxx%3Ayyy&Version=2010-03-31
The only differences seem to be the inclusion of 'Authorization' and 'Signature' headers in the programmatic version (checked using Wireshark).
Any ideas? Thanks in advance!
Update
In my code, if I just programatically do a simple GET request to the SubscribeURL in the SubscriptionConfirmation message this works fine. Just seems odd that the confirmSubscription API call doesn't work. Will probably stick to this workaround for now.
Update 2
Also get the same error when calling sns.unsubscribe although, again, calling the UnsubscribeURL in each notification works. Seems other people have run into that issue too but can't find any solutions.
I faced a similar issue while developing my application.
The way I ended up solving it is the following:
go to IAM and click on your user
go to the permissions tab and click on "Attach Policy"
use the filter to filter for "AmazonSNSFullAccess"
Attach the above policy to your user.
The above should take care of it.
If you wanna be fancy you can create a custom policy that is based on "AmazonSNSFullAccess" and apply it to you user instead.
The custom policy would be something similar to the following:
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"sns:ConfirmSubscription"
],
"Effect": "Allow",
"Resource": "YOUR_RESOURCE_ARN_SHOULD_BE_HERE"
}
]
}
The error says it all:
[AuthorizationError: User: arn:aws:iam::xxx:user/mv-user is not authorized to perform: SNS:ConfirmSubscription on resource: arn:aws:sns:us-east-1:xxx:*]
is basically telling you that the IAM user you're using to call ConfirmSubscription doesn't have the proper permissions to do so. Best bet is to update the permissions for that IAM user, specifically adding ConfirmSubscription permissions.
(Based on your comments, even though the documentation says otherwise, the error is pretty specific... might be worth following up directly with AWS about this issue, since either the error message or documentation is incorrect).

Resources