Proactive messaging in botframework is very slow - performance

I'm trying to send proactive messages using botframework. I have observed that the rate at which botframework is delivering is very slow(3000req/min). Can someone let me know what exactly I should do to make it faster.
All I'm doing is iterating over my users and sending the message using the below code.
var replyActivity = CustomActivityCreator.CreateMessageActivity(message, id);
var result = connector.Conversations.SendToConversationAsync(replyActivity).Result;
Thanks in advance.
PS: My server is hosted in West US.

Related

How to send message activity from Web Chat Bot to Microsoft Teams channel

I have created a Echo Bot in c# using QnA maker which is working absolutely fine now I wanted to achieve a scenario where if user ask any question and bot unable to find related answer than this question must be sent on Microsoft Teams channel where except will reply to the same and that message will sent to the user.
So, Is there any way to send message user message to Microsoft Teams for expert reply. If you have any sample code for the scenario please feel free to mention.
As per your current requirement this is kind of handoff or human live agent connect.
The following way you can achieve posting a message in ms team ( Go through this article Send proactive messages to Teams channels and users ).
Send proactive messages to Teams channels and users ( Microsoft Bot Framework v4 )
The user should be part of ms teams ( Azure AD valid users ).
Suggestions : If you are using domain bot then human live agent or handoff concept is the best approach otherwise you can integrate bin search api or any other third party api for unanswered question.
As per your requirement you can use Graph API to send message to channel using below code
GraphServiceClient graphClient = new GraphServiceClient( authProvider );
var chatMessage = new ChatMessage
{
Body = new ItemBody
{
Content = "Hello World"
}
};
await graphClient.Teams["{team-id}"].Channels["{channel-id}"].Messages
.Request()
.AddAsync(chatMessage);
Please go through this documentation for more info.

How to know if the user has blocked the bot in Teams

I have created a bot using Bot framework V4 and hosted in Teams.
My bot is available for all the users in the organization.
I want to know if someone blocked the bot.
Is there any API or any event from the bot to know the user ID if the Bot has been blocked?
Thanks in Advance
I'm still testing this, so not sure if it really works, but I think if the user has uninstalled an app, then trying to get the "conversation members" will fail, whereas it would succeed otherwise. Code is something like this (C#):
ConnectorClient connector = new ConnectorClient(new Uri(serviceUrl), appId, appSecret);
MicrosoftAppCredentials.TrustServiceUrl(serviceUrl);
var members = connector.Conversations.GetConversationMembersAsync(userConversationId).Result;
That might only work if they're -uninstalled- the app though, versus -blocked- the bot, but it's easy enough to test (I won't have a chance today though).

Can the Powerapps Teams Connector instant message an individual vs posting in a channel?

I currently have a front-desk reception Powerapp that will send a Skype message to whichever employee the visitor selects from the gallery. The employee is notified via Skype message of the visitors arrival. I used SkypeForBusiness.SendMessage connector/function to pull this off. Is there an equivalent in Teams, I have only seen options for posting into public channels. At this time, do you know if the Powerapps Teams connector can send individual private messages to someone via Chat vs Channel? Is this at all possible?
Currently, This is not possible with Connector or Graph APIs. You can use Graph APIs or Connector send messages only to channels.
Bots can send personal as well as channel messages.

Bot Framework v4 - Bot Initiate Conversation

I am developing a bot for Microsoft Teams using the Bot Framework SDK v4 for NodeJS. Is there a way that the bot can automatically initiate a conversation in a channel, rather than user initiating the conversation? My bot works fine when the user initiates the conversation. Any suggestions on how I can proceed with this?
MS Teams calls that a "Proactive Message" (note: Bot Framework generally defines a "proactive message" as sending a user a message not related to current conversation, that you have a reference for. Teams lumps a few things into this category). You can read more about how to use proactive messaging from the official Teams docs. Or, more specifically, creating a channel conversation.
The gist of it is that you need to capture a conversationUpdate and check for a new member added to the conversation or fetch the team roster, then you send the proactive message.
Note: For MS Teams, the user or team will have to add the bot first:
Bots can create new conversations with an individual Microsoft Teams user as long as your bot has user information obtained through previous addition in a personal or team scope. This information enables your bot to proactively notify them. For instance, if your bot was added to a team, it could query the team roster and send users individual messages in personal chats, or a user could #mention another user to trigger the bot to send that user a direct message.
Some developers come across 401: Unauthorized errors when using proactive messaging, especially if the bot was restarted for some reason and the bot is attempting to re-initiate a proactive message. You can read more about preventing that by using trustServiceUrl from this Sample (this is my branch, which is being used to submit a Pull Request to update the Proactive Sample with trustServiceUrl info).
You can initiate a brand new conversation using the connector Client in the Botframework V4 and the Teams Extensions V4. In nodejs, you will find a solution in one of the comments for this Github Issue. For anyone looking for a solution in C#, here is a detailed blog post about accomplishing this in C# version of the botframework.
in nodejs :
var conversationReference = TurnContext.getConversationReference(context.activity)
connectorClient = await createConnectorClient(context)
var conversationParameters = {
isGroup: true,
bot: conversationReference.bot,
channelData: (await teamsCtx.getTeamsChannelData()),
tenantId: teamsCtx.tenant.id,
activity: MessageFactory.text("Queue Summary Placeholder") as Activity
} as ConversationParameters
await connectorClient.conversations.createConversation(conversationParameters)
In C#
ConnectorClient _client = new ConnectorClient(new Uri(turnContext.Activity.ServiceUrl), await GetMicrosoftAppCredentialsAsync(turnContext), new HttpClient());
var channelData = turnContext.Activity.GetChannelData<TeamsChannelData>();
var conversationParameter = new ConversationParameters
{
Bot = turnContext.Activity.Recipient,
IsGroup = true,
ChannelData = channelData,
TenantId = channelData.Tenant.Id,
Activity = MessageFactory.Text(message)
};
var response = await _client.Conversations.CreateConversationAsync(conversationParameter);
Really we need to know when you want the bot to send the message, the bot framework TeamsActivityHandler class provides multiple methods that you can utilise for example:
onMembersAdded(BotHandler): Registers an activity event handler for the members added event, emitted for any incoming conversation update activity that includes members added to the conversation.
Learn more about the events / methods you can utilise here.
I ended up figuring it out and i wrote a bot controller that i can invoke on demand with the following code.
var conversationParameters = new ConversationParameters
{
IsGroup = true,
ChannelData = new TeamsChannelData
{
// this needs to come from the teams context.
Channel = new ChannelInfo(channelId),
},
Activity = (Activity)MessageFactory.Attachment(attachment)
};
// your service url may differ.
MicrosoftAppCredentials.TrustServiceUrl(String.IsNullOrEmpty(serviceUrl) ? constantServiceUrl : serviceUrl, DateTime.MaxValue);
var response = connectorClient.Conversations.CreateConversationAsync(conversationParameters).GetAwaiter().GetResult();

How to enable bot to find Skype group chat it was added to previously?

I am creating a bot with Microsoft Bot Framework that is supposed to, when receives notification from CI server, notify about build events participants of a particular chat group in Skype.
I don't quite get it, when I've added Skype bot to the chat, it has received an activity that presumably would have allowed me to save some Id at that stage. But since I need the bot to be proactive and post messages based on external stimuli, I would need to know the reference to that group chat permanently, including after re-deployment. But after redeployments, I don't have a conversation reference.
In theory, what bit of data, given that I save it during add time, would enable me to proactively send messages at any given point in time?
If it is ok that all participants "join" the conversation by writing first to the bot and if your bot accepts messages in similar Post method
public async Task<HttpResponseMessage> Post([FromBody]Activity activity)
{
string rawActivity = JsonConvert.SerializeObject(activity);
Save(rawActivity);
}
Then you are able to send messages to that conversation from your bot any time by using following code. You can restart or even redeploy your bot in the meantime. I have tested about one week as maximum time between consecutive messages.
public void MethodInvokedByExternalEvent(string externalMessage)
{
var activity = JsonConvert.DeserializeObject<Activity>(GetStoredActivity());
var replyActivity = activity.CreateReply(externalMessage);
ResourceResponse reply = null;
using (var client = new ConnectorClient(new Uri(activity.ServiceUrl)))
{
reply = client.Conversations.ReplyToActivity(replyActivity);
}
}

Resources