/// <summary> /// Create your proactive message here /// </summary> /// <returns></returns> private BotCallbackHandler CreateCallback(ProactiveMessageRequestBody req) { return(async(turnContext, token) => { try { Activity proactiveMessage = turnContext.Activity.CreateReply();; if (req.Attachments != null) { //We want to display multiple attachments as carousel if (req.Attachments.Count > 1) { proactiveMessage = MessageFactory.Carousel(req.Attachments.ToArray()) as Activity; } else { proactiveMessage.Attachments = req.Attachments; } } if (String.IsNullOrEmpty(req.Message)) { proactiveMessage.Text = req.Message; } if (req.SuggestedActions != null) { proactiveMessage.SuggestedActions = req.SuggestedActions; } // Send the user a proactive confirmation message. await turnContext.SendActivityAsync(proactiveMessage); } catch (Exception e) { //TODO handle error logging throw e; } }); }
/// <summary> /// Every conversation turn for our Echo Bot will call this method. /// There are no dialogs used, since it's "single turn" processing, meaning a single /// request and response. /// </summary> /// <param name="turnContext">A <see cref="ITurnContext"/> containing all the data needed /// for processing this conversation turn. </param> /// <param name="cancellationToken">(Optional) A <see cref="CancellationToken"/> that can be used by other objects /// or threads to receive notice of cancellation.</param> /// <returns>A <see cref="Task"/> that represents the work queued to execute.</returns> /// <seealso cref="BotStateSet"/> /// <seealso cref="ConversationState"/> /// <seealso cref="IMiddleware"/> public async Task OnTurnAsync(ITurnContext turnContext, CancellationToken cancellationToken = default(CancellationToken)) { Reference = turnContext.Activity.GetConversationReference(); // Handle Message activity type, which is the main activity type for shown within a conversational interface // Message activities may contain text, speech, interactive cards, and binary or unknown attachments. // see https://aka.ms/about-bot-activity-message to learn more about the message and other activity types if (turnContext.Activity.Type == ActivityTypes.Message) { //This should be sent out from your backend responsbile for generating proactive message requests //Bellow you can find examples of supported content for proactive message by this sample if (turnContext.Activity.Text.ToLower().StartsWith("proactive")) { var card = new HeroCard { Text = "You can upload an image or select one of the following choices", Buttons = new List <CardAction>() { new CardAction(ActionTypes.ImBack, title: "1. Inline Attachment", value: "1"), new CardAction(ActionTypes.ImBack, title: "2. Internet Attachment", value: "2"), new CardAction(ActionTypes.ImBack, title: "3. Uploaded Attachment", value: "3"), } }; var sa = new SuggestedActions() { Actions = new List <CardAction>() { new CardAction() { Title = "Red", Type = ActionTypes.ImBack, Value = "Red" }, new CardAction() { Title = "Yellow", Type = ActionTypes.ImBack, Value = "Yellow" }, new CardAction() { Title = "Blue", Type = ActionTypes.ImBack, Value = "Blue" }, } }; var message = new ProactiveMessageRequestBody() { ConversationReference = await _accessors.ConversationReferenceState.GetAsync(turnContext), Message = "Hello", Attachments = new List <Attachment>() { card.ToAttachment(), card.ToAttachment() }, SuggestedActions = sa }; //SET this based on the adress of your proactive endpoint var localProactiveEndpoint = "http://localhost:3978/api/proactive"; await turnContext.SendActivityAsync("Proactive message incoming..."); // send the conversation reference and message to the bot's proactive endpoint var messageContent = JsonConvert.SerializeObject(message); //In production this would be implemented on the side of backend service, which initiates proactive messages using (var client = new HttpClient()) { var buffer = System.Text.Encoding.UTF8.GetBytes(messageContent); var byteContent = new ByteArrayContent(buffer); byteContent.Headers.ContentType = new MediaTypeHeaderValue("application/json"); var result = await client.PostAsync(localProactiveEndpoint, byteContent); } } else { // Get the conversation state from the turn context. var state = await _accessors.CounterState.GetAsync(turnContext, () => new CounterState()); // Bump the turn count for this conversation. state.TurnCount++; // Set the property using the accessor. await _accessors.CounterState.SetAsync(turnContext, state); // Save the new turn count into the conversation state. await _accessors.ConversationState.SaveChangesAsync(turnContext); // Echo back to the user whatever they typed. var responseMessage = $"Turn {state.TurnCount}: You sent '{turnContext.Activity.Text}'\n"; await turnContext.SendActivityAsync(responseMessage); } } else { if (turnContext.Activity.MembersAdded.Count > 0) { foreach (var m in turnContext.Activity.MembersAdded) { if (m.Id != turnContext.Activity.Recipient.Id) { // store the conversation reference for the newly added user // in production scenario you want to store conversation reference in an external store e.g. Cosmos DB, Table Storage etc. await _accessors.ConversationReferenceState.SetAsync(turnContext, turnContext.Activity.GetConversationReference()); await _accessors.ConversationState.SaveChangesAsync(turnContext); } } await turnContext.SendActivityAsync($"{turnContext.Activity.Type} event detected"); } } }