Teams UpdateActivity events difference when you test in newly created teams - c#

We have a Teams bot that posts messages in MS Teams. The first activity of a new conversation is always an adaptive card and once in a while, we update that with a new card. This worked OK until I made a new Team with this bot.
The update we are trying with UpdateActivityAsync, return NotFound.
After some troubleshooting, I noticed the following:
The new team has a different name: 19:...#thread.tacv2 as opposed to 19:...#thread.skype.
When I use an older team, it works as expected.
When I update the activity with text only (so no adaptive card as attachment) it will always update as expected.
After an update with a text, we are able to update with an adaptive card ONCE. After one update with an adaptive card, any subsequent updates with adaptive cards will return NotFound.
So, as a workaround, I now first update with text and immediately after that I send the update with the card. Which is a bad UI thing (flickering) but it works for now.
We use the old bot framework version 3, which I know is not maintained anymore, but as far as I can find, it should still work (no plans to discontinue operation). Also given the above points (specifically point 4) I would expect it uses the same calls under the hood.
So, this works for older teams, but not for a team with #thread.tacv2
await connector.Conversations.UpdateActivityAsync(
teamsConversationId,
activityId,
(Activity)messageWithCard);
And for teams with #thread.tacv2 we now have to use this
var messageWithText = Activity.CreateMessageActivity();
messageWithText.ChannelId = teamsConversationId;
messageWithText.Id = activityId;
messageWithText.Type = ActivityTypes.Message;
messageWithText.Text = "Updated";
await connector.Conversations.UpdateActivityAsync(
teamsConversationId,
activityId,
(Activity)messageWithText);
await connector.Conversations.UpdateActivityAsync(
teamsConversationId,
activityId,
(Activity)messageWithCard);
The exception does not provide too many details:
Operation returned an invalid status code 'NotFound'
Conversation not found.
Does anyone know how to avoid this change between teams and allow updates of activity with cards?
Also (and this is much less important, but I think it's useful to add) I noticed that sometimes (I've seen it twice now) Teams seems unable to render the adaptive card and displays URIObject XML instead, containing error: cards.unsupported. However, if I exit the client and restart it, it renders fine... I have never seen this so far in the old channels.
Teams client version 1.3.00.362 (64-bit) (no dev mode).
Normal Azure tenant (no preview/trial)
EDIT 11/05/2020 It seems that this also happens on teams with the 'old' name (#thread.skype). So the '#thread.tacv2' seems unrelated.

We weren't able to find logs at the exact timestamps that you provided, but did find logs for the conversation ids on those dates and see 404s with the same minute and seconds in UTC. We assume the time stamps that were provided are represented in a different timezone.
From the logs we are seeing the following pattern:
Bot sends PUT activity with card - 404 returned
Bot sends PUT activity with text - 200 returned
Bot sends PUT activity with card - 200 returned
This looks like the same pattern that you shared in your original post.
There is a scenario that's causing 404s to be returned on PUTS whenever the bot tries to update an existing card message with the exact same card after new messages have been sent to a reply chain
These are the repo steps:
Bot send card to reply chain (can be root message or reply message)
Any user sends a message to the chain
Bot attempts to update message with the exact same card
Is it possible that your bot is encountering this? Is there a way to check whether the card your bot is sending in the first PUT request is the same card that is already in the original message

Related

ExampleAssistantV1 with IBM Watson Unity SDK

I have attached the ExampleAssistantV1.cs script to a character in Unity and obtained my services credentials (API key and service URL) from the Assistant I have created.
From my dialog page, I can only see/get my Assistant Name and Assistant ID, but nothing like Workspace ID. I have searched around my bluemix pages and account details for the Assistant service, but cannot seem to find anything about Workspace. Where is this?
The version date when I used Tone Analyzer in Unity worked with the current date (yesterday) so I wonder if the same applies to Assistant? In the code comments, there is no explanation of what this date actually is...
When I run Unity, I get the following error. I could only find two threads on this; both are closed now on GitHub. Could someone please help me understand what I am missing?
[RESTConnector.ProcessRequestQueue()][ERROR] URL: https://gateway-lon.watsonplatform.net/assistant/api/v1/workspaces//message?version=2018-12-27, ErrorCode: 400, Error: 400 Bad Request, Response: {"error":"URL workspaceid parameter 'message' is not a valid GUID.","code":400}
After running in Unity, when I look at my service page, I see a new instance created with a unity-sdk-example-workspace-deleteUpdated message. How did I cause this? Have I done something wrong that this appears new?
If you click the three dots in the image above next to conversation assistant you can click View API Details. You should be able to see your Workspace ID there.
You supply the version date to select the version of the service you want to use in your application. You will be using the last service release on or before the version date supplied. If you use today's date you will be using the latest release of the service.
The issue with the the call is there is no workspaceId supplied. Ideally there should be a null check for this param. I've created an issue for this: https://github.com/watson-developer-cloud/unity-sdk/issues/490
As for the unity-sdk-example-workspace-deleteUpdated it look like you ran the AssistantV1 example. The example runs through each operation in the service and attempts to invoke it. In this case it looks like it failed to delete the workspace or the example was stopped before it was deleted. It is safe to delete this workspace/skill.

Bot can handle request from Skype desktop app, but not from Skype store app

I have written a small chat bot using the MS bot framework. I added the Skype and Web channels, and host the bot on Azure with the smallest pay-as-you-go plan. The bot itself is working nicely, both through the web chat and in Skype conversations, both directly (1on1 chat) as well as in groups, when I'm using the Skype desktop app.
Unfortunately, when using the Skype app installed from the Microsoft store, nothing works anymore... Sending a message to the bot (in direct chats and groups) always produces HTTP 500 responses from my bot. Digging into it a bit releaved a simple NullReferenceException being thrown, apparently in the very first line in my dialog handler (see below): The call stack pointed at this line, but the error happened later, see below:
namespace MyBot.Dialogs {
[Serializable]
public class RootDialog: IDialog<IMessageActivity> {
public Task StartAsync(IDialogContext context) {
context.Wait(MessageReceivedAsync);
return Task.CompletedTask;
}
private async Task MessageReceivedAsync(IDialogContext context, IAwaitable<IMessageActivity> result) {
// call stack pointed to next line
Activity activity = await result as Activity;
//... some unproblematic stuff
string username = activity.From.Name;
// the next line was the actual problem:
if(username.Contains(" "))
//...
}
}
}
This part of the code, as well as the full MessagesController are taken without changed from the bot framework examples, and as mentioned before, the bot is working fine from web chat and the "regular" Skype desktop app. Even in a group chat with some users on the desktop app and some on the store app, the users with the desktop app can interact with the bot as expected, while the store app users only trigger errors.
The obvious questions here are of course: how (and why) do the two Skype apps differ from a bot perspective, and how can I handle this?
Edit: As it turns out, the Skype desktop app sets the activity.From.Name property to the user's name, while the Skype store app does not. The mean part is, the channelid's for both are the same ("skype", obviously).
Thanks to the comment of #EricDahlvang, I noticed that the error was not the line mentioned above at first, despite the call stack specifically giving this line number. The error happened later, when I tried to work with "activity.From.Name". As it turns out, the regular Skype sets this property to match the users display name, while the Skype store app does not, and returns null.

UCMA recording app

I've installed a MSPL script to redirect INVITE audio messages to the UCMA sip address
I'm currently writing a UCMA app for Skype for Business to:
receive incoming calls
accept the call
create a conference call
add a trusted participant to the conference
create a recording instance on the trusted participant audio flow to record the conversation
The last thing I need to do is add the To caller URI to the conference call.
I've tried to invite the new participant into the conference using the code examples from this article, but I get an exception saying there are no AvailableMediaTypes in the conversation.
public static async void InviteToConference(string destinationUri)
{
//Create a new conversation for the application endpoint.
_toConversation = new Conversation(_server.ApplicationEndPoint);
var conferenceInviteSettings = new ConferenceInvitationSettings();
conferenceInviteSettings.ConferenceUri = _conferenceUri;
ConferenceInvitation invitation = new ConferenceInvitation(_toConversation, conferenceInviteSettings);
try
{
await invitation.DeliverAsync(destinationUri);
}
catch (InvalidOperationException)
{
// Conversation was terminated while trying to add participant.
}
}
Can someone please show me what I need to do to add / invite a participant into a conference call?
It would be even better if someone could show me how to record a Skype for Business call without the need to create a conference, as a conference can't be forwarded.
Your code looks like the old way (UCMA 3) of doing it. Have you tried this.
e.g.
McuDialOutOptions mcuDialOutOptions = new McuDialOutOptions();
mcuDialOutOptions.ParticipantUri = "sip:alice#contoso.com";
mcuDialOutOptions.ParticipantDisplayName = "Alice";
mcuDialOutOptions.PreferredLanguage = CultureInfo.GetCultureInfo("en-us");
conversation.ConferenceSession.AudioVideoMcuSession.BeginDialOut("tel:+14255551234", mcuDialOutOptions, dialOutCallback, state);
Using this sort of method to record very specific and low traffic should be fine but when you start to scale it up then you are going to hit all sorts of problems.
As for how to do it without a conference:
There is no way to do it fully with the supplied Microsoft API's.
What you have to do is implement, buy or use open source libraries for the following pieces:
sniff network packets
decode RTP/SRTP streams
decode the audio and/or video codecs used between the callers
encode streams into your desired format and save somewhere
To get access to the SRTP streams encryption setup and to figure out what the dynamic payload types for the audio/video codecs used, you also need to know the SDP offered and answered between the calling parties. You also need access to the SIP traffic to determine the calling parties to know who called who. This can be a lot more trouble than what it seems...
To get the SIP/SDP information there are two options that I know of:
Skype/Lync Server SDK (MSPL / Server Application) to see most of the SIP traffic. This is what I've used to implement a recording solution.
Skype/Lync SDN SDK - I haven't used this API but it seems to give access to the SDP so it should work.
If you get all these peices into place then the next problem is you can only "record" (basically "sniff") what you can see. If you can't see the RTP/SRTP traffic you can't record the calls.
So you need to have the sniffer part of the recording software on areas of the network that see the traffic you want to record. For example if you wish to record all PSTN calls, you can have a network spanning port off the Skype mediation servers.
If you wish to record ALL calls, then that gets a lot harder. You most likely need to either:
Force all media trafic to go through a known place (like the Edge server) and put sniffers on the that network.
Have lots of sniffers in strategic areas of the network to capture most RTP/SRTP traffic.
The problems with the above solutions are:
Forcing all the traffic through one point can cause performance issues (like you will see with your conference setup) once load starts to increase. Also forcing external (edge server users) and/or federated calls through this one point can cause a problems. Think edger server user calls to edge server users where the media traffic may not even go into your network at all but live only on the internet. Forcing the trafficing into your network can cause performance issues.
When not forcing all the traffic through one point, you may never be see all skype user to skype user calls depending on your network setup. Calls between Edge server skype users are even more of a problem as the media traffic may not even enter your network at all.
On top of all that there are the general problems of storage management (recording after a while will start taking up a large amount of disk space) and call recording management (e.g. searching for a specific call) and user security around these recordings to deal with. I'm sure I'm missing a lot but those are the basics.
If recording in not going to be a core component, you could just buy a 3rd party call recording solution that supports Lync/Skype.

Connecting a MS bot framework user to someone on Skype

I've made a chat bot using Microsoft Bot Framework which answers a user's questions. When the bot is unable to answer the user's questions, I want to be able to redirect the user question to a customer rep on Skype.
The person on Skype will see the messages posted by the user, and his answers will be sent to the user.
I need some advice on how to achieve this connection (from user<->chatbot<->SkypecustomerRep)
Edit:
I'm toying with the idea of using the commands in http://docs.botframework.com/connector/new-conversations/#navtitle
I figured when the LuisIntent would turn out to be None, I'd message a skype id with:
var connector = new ConnectorClient();
var message = new Message
{
From = new ChannelAccount(channelId: ""),
To = new ChannelAccount() {ChannelId = "Skype", Address = "xyz#abc.com"},
Text = result.Query,
Language = "en"
};
where the email is the Skype id. I'm not able to figure out what should be in the From field (what's the channelId, Address of my bot)
EDIT:
I'm able to pass one message to Skype now, but when the Skype user replies, I observe that the reply is not immediately presented to the bot framework user. In other words, when the user types something into the chat window, he gets a response from the bot (as expected) and the skype user's delayed message.
If you want the customer support representative to have sufficient context (i.e. see more than just the most recent text posted by the user) you are going to need to build your own customer support interface to both record conversations as well as highlight those that need attention from a human. Usually folks do this building their own client with DirectLine or connecting up their existing customer support client (also with DirectLine). The bot then directly passes the support reps replies back to the end users.
Some additional detail can be seen in this previous answer.

Content webservice call not refreshed in windows phone

Currently, I'm developing a Windows Phone 8.0 application that displays some 100 GPS locations on a map. The GPS data is obtained by calling a RESTful webservice as follows:
public async Task<string> GetWebContent(string uri)
{
string result = null;
using (var client = new HttpClient())
{
result = await client.GetStringAsync(new Uri(uri));
}
return result;
}
Here, the HttpClient is taken from the Nuget Package "Microsoft HTTP Client Libraries".
The first time the code is called, data is obtained and the GPS locations are nicely plotted on a map. However, since the GPS devices move constantly, I have to refresh the data every 30 seconds. This is where I hit the wall; the data contained in the variable "result" never changes. Even after several minutes the data is the same. The raw data contain a datetime property, which clearly tells me that the data is old and not just the GPS devices standing still. If I paste the uri into a webbrowser, and hit the refresh butten every 15 sec, the data does changed hence the webservice is working properly.
Since the HttpClient is contained in a using-statement, it is disposed off every time and some hidden caching mechanism seems impossible. So, does anyone have an idea?
cheers
Update
I tried using Fiddler, but had to follow a lengthy instruction to make it connect with the emulator. Once done, nothing worked anymore :-s Reverting all the certificates that Fiddler installed and copied the code to a regular WPF application and there it works als a charm.I'm no closer to an understanding of what's going on, but the problem seems to be related to the fact that it's a windows phone project.
It maybe caching the result from the first call. You may need to set the IfModifiedSince property in the request header before each subsequent call to ensure that its getting the latest value.
Example code from: https://stackoverflow.com/a/17884734/61226
client.DefaultRequestHeaders.IfModifiedSince = DateTime.UtcNow;
See similar issues here:
No cache with HttpClient in Windows Phone 8
Caching issue with WebClient/HttpClient

Categories

Resources