protected override async Task <MessagingExtensionActionResponse> OnTeamsMessagingExtensionFetchTaskAsync(ITurnContext <IInvokeActivity> turnContext, MessagingExtensionQuery query, CancellationToken cancellationToken) { var reply = MessageFactory.Text("OnTeamsMessagingExtensionFetchTaskAsync MessagingExtensionQuery: " + JsonConvert.SerializeObject(query)); await turnContext.SendActivityAsync(reply, cancellationToken); var tokenProvider = turnContext.Adapter as IUserTokenProvider; var tokenStatus = await tokenProvider.GetTokenStatusAsync(turnContext, turnContext.Activity.From.Id, cancellationToken : cancellationToken); if (!tokenStatus.Any(t => t.HasToken == true)) { var signInLink = await(turnContext.Adapter as IUserTokenProvider).GetOauthSignInLinkAsync(turnContext, "aadv2", cancellationToken).ConfigureAwait(false); return(new MessagingExtensionActionResponse { ComposeExtension = new MessagingExtensionResult { Type = "auth", SuggestedActions = new MessagingExtensionSuggestedAction() { Actions = new List <CardAction> { new CardAction { Type = ActionTypes.OpenUrl, Value = signInLink, }, }, }, }, }); } return(AdaptiveCardHelper.CreateTaskModuleAdaptiveCardResponse()); }
/// <inheritdoc/> public void BuildAdaptiveCardGroupReply <T>(Activity reply, BotResponse response, string cardPath, string attachmentLayout, List <T> cardDataAdapters, StringDictionary tokens = null) where T : CardDataBase { var tokensCopy = CopyTokens(tokens); var parsedResponse = this.ParseResponse(response, tokensCopy); var parsedCards = this.ParseAndCreateCards(cardPath, cardDataAdapters, tokensCopy, parsedResponse); this.PopulateReplyFromResponse(reply, response); if (cardDataAdapters.Count > 1) { reply.AttachmentLayout = attachmentLayout; } foreach (var card in parsedCards) { reply.Attachments.Add(AdaptiveCardHelper.CreateCardAttachment(card)); } if (response.SuggestedActions?.Length > 0) { reply.SuggestedActions = new SuggestedActions( actions: response.SuggestedActions.Select(choice => new CardAction( ActionTypes.ImBack, choice, value: choice.ToLower(), displayText: choice.ToLower(), text: choice.ToLower())).ToList()); } }
protected override async Task <MessagingExtensionActionResponse> OnTeamsMessagingExtensionFetchTaskAsync(ITurnContext <IInvokeActivity> turnContext, MessagingExtensionQuery query, CancellationToken cancellationToken) { var reply = MessageFactory.Text("OnTeamsMessagingExtensionFetchTaskAsync MessagingExtensionQuery: " + JsonConvert.SerializeObject(query)); await turnContext.SendActivityAsync(reply, cancellationToken); return(AdaptiveCardHelper.CreateTaskModuleAdaptiveCardResponse()); }
protected override Task <MessagingExtensionActionResponse> OnTeamsMessagingExtensionBotMessagePreviewEditAsync(ITurnContext <IInvokeActivity> turnContext, MessagingExtensionAction action, CancellationToken cancellationToken) { // The data has been returned to the bot in the action structure. var activityPreview = action.BotActivityPreview[0]; var attachmentContent = activityPreview.Attachments[0].Content; var previewedCard = JsonConvert.DeserializeObject <AdaptiveCard>(attachmentContent.ToString(), new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore }); var exampleData = AdaptiveCardHelper.CreateExampleData(previewedCard); // This is a preview edit call and so this time we want to re-create the adaptive card editor. var adaptiveCardEditor = AdaptiveCardHelper.CreateAdaptiveCardEditor(exampleData); return(Task.FromResult(new MessagingExtensionActionResponse { Task = new TaskModuleContinueResponse { Value = new TaskModuleTaskInfo { Card = new Attachment { Content = adaptiveCardEditor, ContentType = AdaptiveCard.ContentType, }, Height = 450, Width = 500, Title = "Task Module Fetch Example", }, }, })); }
/// <inheritdoc/> public void BuildAdaptiveCardReply <T>(Activity reply, BotResponse response, string cardPath, T cardDataAdapter, StringDictionary tokens = null) where T : CardDataBase { var tokensCopy = CopyTokens(tokens); var parsedResponse = this.ParseResponse(response, tokensCopy); var parsedCards = this.ParseAndCreateCards(cardPath, new List <T> { cardDataAdapter }, tokensCopy, parsedResponse); this.PopulateReplyFromResponse(reply, response); if (reply.Attachments == null) { reply.Attachments = new List <Attachment>(); } reply.Attachments.Add(AdaptiveCardHelper.CreateCardAttachment(parsedCards[0])); if (response.SuggestedActions?.Length > 0) { reply.SuggestedActions = new SuggestedActions( actions: response.SuggestedActions.Select(choice => new CardAction( ActionTypes.ImBack, choice, value: choice.ToLower(), displayText: choice.ToLower(), text: choice.ToLower())).ToList()); } }
// Helper function for building the TaskInfo object based on the incoming request private static Models.TaskInfo GetTaskInfo(string actionInfo) { Models.TaskInfo taskInfo = new Models.TaskInfo(); switch (actionInfo) { case TaskModuleIds.YouTube: taskInfo.Url = taskInfo.FallbackUrl = ApplicationSettings.BaseUrl + "/" + TaskModuleIds.YouTube; SetTaskInfo(taskInfo, TaskModuleUIConstants.YouTube); break; case TaskModuleIds.MsStream: taskInfo.Url = taskInfo.FallbackUrl = ApplicationSettings.BaseUrl + "/" + TaskModuleIds.MsStream; SetTaskInfo(taskInfo, TaskModuleUIConstants.MsStream); break; case TaskModuleIds.PowerApp: taskInfo.Url = taskInfo.FallbackUrl = ApplicationSettings.BaseUrl + "/" + TaskModuleIds.PowerApp; SetTaskInfo(taskInfo, TaskModuleUIConstants.PowerApp); break; case TaskModuleIds.CustomForm: taskInfo.Url = taskInfo.FallbackUrl = ApplicationSettings.BaseUrl + "/" + TaskModuleIds.CustomForm; SetTaskInfo(taskInfo, TaskModuleUIConstants.CustomForm); break; case TaskModuleIds.AdaptiveCard: taskInfo.Card = AdaptiveCardHelper.GetAdaptiveCard(); SetTaskInfo(taskInfo, TaskModuleUIConstants.AdaptiveCard); break; default: break; } return(taskInfo); }
protected override async Task <MessagingExtensionActionResponse> OnTeamsMessagingExtensionBotMessagePreviewSendAsync(ITurnContext <IInvokeActivity> turnContext, MessagingExtensionAction action, CancellationToken cancellationToken) { // The data has been returned to the bot in the action structure. var activityPreview = action.BotActivityPreview[0]; var attachmentContent = activityPreview.Attachments[0].Content; var previewedCard = JsonConvert.DeserializeObject <AdaptiveCard>(attachmentContent.ToString(), new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore }); var exampleData = AdaptiveCardHelper.CreateExampleData(previewedCard); // This is a send so we are done and we will create the adaptive card editor. var adaptiveCard = AdaptiveCardHelper.CreateAdaptiveCard(exampleData); var message = MessageFactory.Attachment(new Attachment { ContentType = AdaptiveCard.ContentType, Content = adaptiveCard }); // THIS WILL WORK IF THE BOT IS INSTALLED. (GetMembers() will NOT throw if the bot is installed.) // (The application should fail gracefully.) var channelId = turnContext.Activity.TeamsGetChannelId(); //await turnContext.TeamsCreateConversationAsync(channelId, message, cancellationToken); return(null); }
public void Test_GetCardFromJson() { List <string> testData = new List <string>(); // 1# case with \r\n testData.Add("Hello \r\n\r\nYour agenda for Tuesday, November 13, 2018\r\n\r\n\r\nMulti-day\r\nEnds Wed 11/21\r\n\r\n\r\n\r\n\r\n\r\n\r\nvacation\r\n\r\n\r\n\r\n\r\n\r\n\r\nAgenda mail settings\r\nUnsubscribe • Privacy statement\r\nMicrosoft Corporation, One Microsoft Way, Redmond, WA 98052"); // 2# case with " testData.Add("\""); // 3# case with ' testData.Add("\'"); // 4# case with \ testData.Add("2\\3"); // 5# case with \\ testData.Add("\\\\"); // 6# case with / testData.Add("/"); // 7# case with \b testData.Add("\b"); // 8# case with \f testData.Add("\f"); // 9# case with \n testData.Add("\n"); // 10# case with \r testData.Add("\r"); // 11# case with \t testData.Add("\t"); foreach (var testContent in testData) { var card = AdaptiveCardHelper.GetCardFromJson(cardJson, GetSpecialCharToken(testContent)); Assert.IsNotNull(card); } }
/// <summary> /// Add a new suggestion in company response entity in Microsoft Azure Table storage. /// </summary> /// <param name="turnContext">Context object containing information cached for a single turn of conversation with a user.</param> /// <param name="userRequestDetails">User response new request details object used to send new request data.</param> /// <param name="customAPIAuthenticationToken">Generate JWT token used by client application to authenticate HTTP calls with API.</param> /// <param name="cancellationToken">Propagates notification that operations should be canceled.</param> /// <returns>A task that represents the work queued to execute.</returns> private async Task <MessagingExtensionActionResponse> AddNewSuggestionResultAsync( ITurnContext <IInvokeActivity> turnContext, AddUserResponseRequestDetail userRequestDetails, string customAPIAuthenticationToken, CancellationToken cancellationToken) { var activity = turnContext.Activity; var companyResponseEntity = await this.companyStorageHelper.AddNewSuggestionAsync(activity, userRequestDetails); // Parse team channel deep link URL and get team id. var teamId = AdaptiveCardHelper.ParseTeamIdFromDeepLink(this.botSetting.Value.TeamIdDeepLink); if (string.IsNullOrEmpty(teamId)) { throw new NullReferenceException("Provided team details seems to incorrect, please reach out to the Admin."); } var isAddSuggestionSuccess = await this.companyResponseStorageProvider.UpsertConverationStateAsync(companyResponseEntity); if (isAddSuggestionSuccess) { // Tracking for company response suggested request. this.RecordEvent(RecordSuggestCompanyResponse, turnContext); var attachment = AdminCard.GetNewResponseRequestCard(companyResponseEntity, localizer: this.localizer); var resourceResponse = await this.SendCardToTeamAsync(turnContext, attachment, teamId, cancellationToken); companyResponseEntity.ActivityId = resourceResponse.ActivityId; await this.companyResponseStorageProvider.UpsertConverationStateAsync(companyResponseEntity); return(new MessagingExtensionActionResponse { Task = new TaskModuleContinueResponse { Value = new TaskModuleTaskInfo { Url = $"{this.options.Value.AppBaseUri}/response-message?token={customAPIAuthenticationToken}&status=addSuccess&isCompanyResponse=true&message={this.localizer.GetString("AddNewSuggestionSuccessMessage")}&telemetry=${this.telemetrySettings.Value.InstrumentationKey}&theme=" + "{theme}&locale=" + "{locale}", Height = TaskModuleHeight, Width = TaskModuleWidth, Title = this.localizer.GetString("ManageYourResponsesTitleText"), }, }, }); } else { return(new MessagingExtensionActionResponse { Task = new TaskModuleContinueResponse { Value = new TaskModuleTaskInfo { Url = $"{this.options.Value.AppBaseUri}/response-message?token={customAPIAuthenticationToken}&status=editFailed&isCompanyResponse=true&message={this.localizer.GetString("AddNewSuggestionFailedMessage")}&theme=" + "{theme}&locale=" + "{locale}", Height = TaskModuleHeight, Width = TaskModuleWidth, Title = this.localizer.GetString("ManageYourResponsesTitleText"), }, }, }); } }
/// <summary> /// Send the adaptive card in reply to the original activity /// </summary> /// <param name="connectorClient">Connector client</param> /// <param name="originalActivity">Activity we will reply to</param> /// <param name="adaptiveCard">Adaptive card to show</param> /// <returns>Task</returns> public static Task ReplyWithAdaptiveCard(ConnectorClient connectorClient, Activity originalActivity, AdaptiveCard adaptiveCard) { var replyActivity = originalActivity.CreateReply(); replyActivity.Attachments = new List <Attachment> { AdaptiveCardHelper.CreateAdaptiveCardAttachment(adaptiveCard) }; return(connectorClient.Conversations.ReplyToActivityAsync(replyActivity)); }
public static async Task RespondAsync(DialogContext dc, RecognizerResult luisResults) { if (Hosts.TryGetHost(luisResults, out Host host)) { await AdaptiveCardHelper.SendCardFromFileAsync(dc, host.GetVersionsFilePath()); } else { await dc.Context.SendActivityAsync("Please specify which host you're curious about, like \"What version is supported in Outlook?\""); } }
protected override async Task <MessagingExtensionActionResponse> OnTeamsMessagingExtensionBotMessagePreviewEditAsync(ITurnContext <IInvokeActivity> turnContext, MessagingExtensionAction action, CancellationToken cancellationToken) { var submitData = action.ToSubmitExampleData(); return(AdaptiveCardHelper.CreateTaskModuleAdaptiveCardResponse( submitData.Question, bool.Parse(submitData.MultiSelect), submitData.Option1, submitData.Option2, submitData.Option3)); }
private async Task HandleDebugWelcomeTeam(ConnectorClient connectorClient, Activity activity, string teamId) { var welcomeCard = WelcomeTeamAdaptiveCard.GetCardJson("TestTeam", teamId, activity.Recipient.Id, "Rocky"); var replyActivity = activity.CreateReply(); replyActivity.Attachments = new List <Attachment> { AdaptiveCardHelper.CreateAdaptiveCardAttachment(welcomeCard) }; await connectorClient.Conversations.ReplyToActivityAsync(replyActivity); }
private async Task HandleDebugNotifyUser(ConnectorClient connectorClient, Activity activity, TeamsChannelAccount sender) { var notifyCard = PairUpNotificationAdaptiveCard.GetCardJson("TestTeam", sender, sender, "LunchBuddy"); var replyActivity = activity.CreateReply(); replyActivity.Attachments = new List <Attachment> { AdaptiveCardHelper.CreateAdaptiveCardAttachment(notifyCard) }; await connectorClient.Conversations.ReplyToActivityAsync(replyActivity); }
private List <AdaptiveCard> ParseAndCreateCards <T>(string cardPath, List <T> cardDataAdapters, StringDictionary tokens, BotResponse parsedResponse) where T : CardDataBase { if (!tokens.ContainsKey("Text")) { tokens.Add("Text", parsedResponse.Reply.Text); } if (!tokens.ContainsKey("Speak")) { tokens.Add("Speak", parsedResponse.Reply.Speak); } var properties = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance); foreach (var property in properties) { if (!tokens.ContainsKey(property.Name)) { tokens.Add(property.Name, string.Empty); } } // Create list of cards. var cards = new List <AdaptiveCard>(); foreach (var cardDataAdapter in cardDataAdapters) { // Add or update the public properties of the data type for the card to the tokens list. foreach (var property in properties) { var value = cardDataAdapter.GetType().GetProperty(property.Name).GetValue(cardDataAdapter, null)?.ToString(); if (value != null) { value = SimpleTokensRegex.Replace(value, match => tokens[match.Groups[1].Value]); } if (!tokens.ContainsKey(property.Name)) { tokens.Add(property.Name, value); } else { tokens[property.Name] = value; } } cards.Add(AdaptiveCardHelper.GetCardFromJson(cardPath, tokens)); } return(cards); }
protected override Task <MessagingExtensionActionResponse> OnTeamsMessagingExtensionSubmitActionAsync(ITurnContext <IInvokeActivity> turnContext, MessagingExtensionAction action, CancellationToken cancellationToken) { var exampleData = JsonConvert.DeserializeObject <ExampleData>(action.Data.ToString()); var adaptiveCard = AdaptiveCardHelper.CreateAdaptiveCard(exampleData); // a number of reasonable options here... // (1) send a message on a new conversation and return null (only works in group chats and teams) // THIS WILL WORK IF THE BOT IS INSTALLED. (GetMembers() will NOT throw if the bot is installed.) //var message = MessageFactory.Attachment(new Attachment { ContentType = AdaptiveCard.ContentType, Content = adaptiveCard }); //var channelId = turnContext.Activity.TeamsGetChannelId(); //await turnContext.TeamsCreateConversationAsync(channelId, message, cancellationToken); //return null; // (2) drop the content into the compose window ready for the user to send //return new MessagingExtensionActionResponse //{ // ComposeExtension = new MessagingExtensionResult // { // Type = "result", // AttachmentLayout = "list", // Attachments = new List<MessagingExtensionAttachment> // { // new MessagingExtensionAttachment // { // Content = adaptiveCard, // ContentType = AdaptiveCard.ContentType, // }, // }, // }, //}; // (3) start a preview flow return(Task.FromResult(new MessagingExtensionActionResponse { ComposeExtension = new MessagingExtensionResult { Type = "botMessagePreview", ActivityPreview = MessageFactory.Attachment(new Attachment { Content = adaptiveCard, ContentType = AdaptiveCard.ContentType, }) as Activity, }, })); }
protected override async Task <MessagingExtensionActionResponse> OnTeamsMessagingExtensionBotMessagePreviewEditAsync(ITurnContext <IInvokeActivity> turnContext, MessagingExtensionAction action, CancellationToken cancellationToken) { var reply = MessageFactory.Text("OnTeamsMessagingExtensionBotMessagePreviewEditAsync MessagingExtensionAction: " + JsonConvert.SerializeObject(action)); await turnContext.SendActivityAsync(reply, cancellationToken); var submitData = action.ToSubmitExampleData(); return(AdaptiveCardHelper.CreateTaskModuleAdaptiveCardResponse( submitData.Question, bool.Parse(submitData.MultiSelect), submitData.Option1, submitData.Option2, submitData.Option3)); }
// Will be called when user triggers messaging extension protected override async Task <MessagingExtensionActionResponse> OnTeamsMessagingExtensionFetchTaskAsync(ITurnContext <IInvokeActivity> turnContext, MessagingExtensionAction action, CancellationToken cancellationToken) { AdaptiveCard adaptiveCardEditor; try { // create task action var cardModel = new CardDataModel(); if (action.CommandId.Equals("CreateCalendarEvent")) { var taskTitle = "Enter Task Title";; if (action.MessagePayload.Body.Content.ToString().Contains("attachment id")) { var temp = action.MessagePayload.Attachments[0].Content.ToString(); var objAttachment = JsonConvert.DeserializeObject <CCCardAttachmentModel>(temp); taskTitle = objAttachment.body[0].text; } else { taskTitle = action.MessagePayload.Body.Content.ToString(); } cardModel.TaskTitle = taskTitle; } adaptiveCardEditor = AdaptiveCardHelper.CreateCardCalendarEventInputs(cardModel); } catch (Exception ex) { throw ex; } return(await Task.FromResult(new MessagingExtensionActionResponse { Task = new TaskModuleContinueResponse { Value = new TaskModuleTaskInfo { Card = new Microsoft.Bot.Schema.Attachment { Content = adaptiveCardEditor, ContentType = AdaptiveCard.ContentType, }, Height = 350, Width = 400, Title = "Event Creation", }, }, })); //Needs to be replaced with OAuth Prompt }
private async Task HandleDebugWelcomeUser(ConnectorClient connectorClient, Activity activity, string teamId) { var welcomeCard = WelcomeNewMemberAdaptiveCard.GetCard( new TeamContext { TeamId = teamId, TeamName = "TestTeam" }, Model.EnrollmentStatus.NotJoined, "InstallerPerson", false); var replyActivity = activity.CreateReply(); replyActivity.Attachments = new List <Attachment> { AdaptiveCardHelper.CreateAdaptiveCardAttachment(welcomeCard) }; await connectorClient.Conversations.ReplyToActivityAsync(replyActivity); }
protected override async Task <MessagingExtensionActionResponse> OnTeamsMessagingExtensionBotMessagePreviewSendAsync(ITurnContext <IInvokeActivity> turnContext, MessagingExtensionAction action, CancellationToken cancellationToken) { // The data has been returned to the bot in the action structure. var activityPreview = action.BotActivityPreview[0]; var attachmentContent = activityPreview.Attachments[0].Content; var previewedCard = JsonConvert.DeserializeObject <AdaptiveCard>(attachmentContent.ToString(), new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore }); var exampleData = AdaptiveCardHelper.CreateExampleData(previewedCard); // This is a send so we are done and we will create the adaptive card editor. var adaptiveCard = AdaptiveCardHelper.CreateAdaptiveCard(exampleData); var message = MessageFactory.Attachment(new Attachment { ContentType = AdaptiveCard.ContentType, Content = adaptiveCard }); // THIS WILL WORK IF THE BOT IS INSTALLED. (GetMembers() will NOT throw if the bot is installed.) // (The application should fail gracefully.) var channelId = turnContext.Activity.TeamsGetChannelId(); var conversationParameters = new ConversationParameters { IsGroup = true, ChannelData = new TeamsChannelData { Channel = new ChannelInfo(channelId) }, Activity = (Activity)message, }; var connectorClient = turnContext.TurnState.Get <IConnectorClient>(); // This call does NOT send the outbound Activity is not being sent through the middleware stack. var conversationResourceResponse = await connectorClient.Conversations.CreateConversationAsync(conversationParameters, cancellationToken).ConfigureAwait(false); var attachments = new MessagingExtensionAttachment(AdaptiveCard.ContentType, null, adaptiveCard); var result = new MessagingExtensionResult(AttachmentLayoutTypes.List, "result", new[] { attachments }, null); return(new MessagingExtensionActionResponse() { ComposeExtension = result, }); }
protected override async Task <MessagingExtensionActionResponse> OnTeamsMessagingExtensionBotMessagePreviewSendAsync(ITurnContext <IInvokeActivity> turnContext, MessagingExtensionAction action, CancellationToken cancellationToken) { // The data has been returned to the bot in the action structure. var activityPreview = action.BotActivityPreview[0]; var attachmentContent = activityPreview.Attachments[0].Content; var previewedCard = JsonConvert.DeserializeObject <AdaptiveCard>(attachmentContent.ToString(), new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore }); var exampleData = AdaptiveCardHelper.CreateExampleData(previewedCard); // This is a send so we are done and we will create the adaptive card editor. var adaptiveCard = AdaptiveCardHelper.CreateAdaptiveCard(exampleData); var message = MessageFactory.Attachment(new Attachment { ContentType = AdaptiveCard.ContentType, Content = adaptiveCard }); //User Attribution for Bot messages if (exampleData.UserAttributionSelect == "true") { message.ChannelData = new { OnBehalfOf = new[] { new { ItemId = 0, MentionType = "person", Mri = turnContext.Activity.From.Id, DisplayName = turnContext.Activity.From.Name } } }; } // THIS WILL WORK IF THE BOT IS INSTALLED. (SendActivityAsync will throw if the bot is not installed.) await turnContext.SendActivityAsync(message, cancellationToken); return(null); }
private List <Attachment> GetAdaptiveCard(QnAMakerResults result) { var attachments = new List <Attachment>(); foreach (var res in result.Answers) { var card = AdaptiveCardHelper.GetAdaptiveCard(res); attachments.Add(new Attachment { ContentType = AdaptiveCard.ContentType, Content = card, Name = "Suggestion" }); if (res.Score >= 0.95) { break; } } return(attachments); }
protected override Task <MessagingExtensionActionResponse> OnTeamsMessagingExtensionFetchTaskAsync(ITurnContext <IInvokeActivity> turnContext, MessagingExtensionAction action, CancellationToken cancellationToken) { var adaptiveCardEditor = AdaptiveCardHelper.CreateAdaptiveCardEditor(); return(Task.FromResult(new MessagingExtensionActionResponse { Task = new TaskModuleContinueResponse { Value = new TaskModuleTaskInfo { Card = new Attachment { Content = adaptiveCardEditor, ContentType = AdaptiveCard.ContentType, }, Height = 450, Width = 500, Title = "Task Module Fetch Example", }, }, })); }
public static AdaptiveCard CreateIncidentAdaptiveCard(string botId = null) { // Json Card for creating incident // TODO: Replace with Cards.Lg and responses AdaptiveCard adaptiveCard = AdaptiveCardHelper.GetCardFromJson("Dialogs/Teams/Resources/CreateIncident.json"); adaptiveCard.Id = "GetUserInput"; adaptiveCard.Actions.Add(new AdaptiveSubmitAction() { Title = "SubmitIncident", Data = new AdaptiveCardValue <TaskModuleMetadata>() { Data = new TaskModuleMetadata() { SkillId = botId, TaskModuleFlowType = TeamsFlowType.CreateTicket_Form.ToString(), Submit = true } } }); return(adaptiveCard); }
/// <summary> /// Handle adaptive card submit in 1:1 chat. /// Submits the question or feedback to the SME team. /// </summary> /// <param name="message">A message in a conversation.</param> /// <param name="turnContext">Context object containing information cached for a single turn of conversation with a user.</param> /// <param name="cancellationToken">Propagates notification that operations should be canceled.</param> /// <returns>A task that represents the work queued to execute.</returns> private async Task OnAdaptiveCardSubmitInPersonalChatAsync( IMessageActivity message, ITurnContext <IMessageActivity> turnContext, CancellationToken cancellationToken) { Attachment smeTeamCard = null; // Notification to SME team Attachment userCard = null; // Acknowledgement to the user TicketEntity newTicket = null; // New ticket switch (message?.Text) { case Constants.AskAnExpert: this.logger.LogInformation("Sending user ask an expert card (from answer)"); var askAnExpertPayload = ((JObject)message.Value).ToObject <ResponseCardPayload>(); await turnContext.SendActivityAsync(MessageFactory.Attachment(AskAnExpertCard.GetCard(askAnExpertPayload))).ConfigureAwait(false); break; case Constants.ShareFeedback: this.logger.LogInformation("Sending user share feedback card (from answer)"); var shareFeedbackPayload = ((JObject)message.Value).ToObject <ResponseCardPayload>(); await turnContext.SendActivityAsync(MessageFactory.Attachment(ShareFeedbackCard.GetCard(shareFeedbackPayload))).ConfigureAwait(false); break; case AskAnExpertCard.AskAnExpertSubmitText: this.logger.LogInformation("Received question for expert"); newTicket = await AdaptiveCardHelper.AskAnExpertSubmitText(message, turnContext, cancellationToken, this.ticketsProvider).ConfigureAwait(false); if (newTicket != null) { smeTeamCard = new SmeTicketCard(newTicket).ToAttachment(message?.LocalTimestamp); userCard = new UserNotificationCard(newTicket).ToAttachment(Strings.NotificationCardContent, message?.LocalTimestamp); } break; case ShareFeedbackCard.ShareFeedbackSubmitText: this.logger.LogInformation("Received app feedback"); smeTeamCard = await AdaptiveCardHelper.ShareFeedbackSubmitText(message, turnContext, cancellationToken).ConfigureAwait(false); if (smeTeamCard != null) { await turnContext.SendActivityAsync(MessageFactory.Text(Strings.ThankYouTextContent)).ConfigureAwait(false); } break; default: var payload = ((JObject)message.Value).ToObject <ResponseCardPayload>(); if (payload.IsPrompt) { this.logger.LogInformation("Sending input to QnAMaker for prompt"); await this.GetQuestionAnswerReplyAsync(turnContext, message).ConfigureAwait(false); } else { this.logger.LogWarning($"Unexpected text in submit payload: {message.Text}"); } break; } string expertTeamId = await this.configurationProvider.GetSavedEntityDetailAsync(ConfigurationEntityTypes.TeamId).ConfigureAwait(false); // Send message to SME team. if (smeTeamCard != null) { var resourceResponse = await this.SendCardToTeamAsync(turnContext, smeTeamCard, expertTeamId, cancellationToken).ConfigureAwait(false); // If a ticket was created, update the ticket with the conversation info. if (newTicket != null) { newTicket.SmeCardActivityId = resourceResponse.ActivityId; newTicket.SmeThreadConversationId = resourceResponse.Id; await this.ticketsProvider.UpsertTicketAsync(newTicket).ConfigureAwait(false); } } // Send acknowledgment to the user if (userCard != null) { await turnContext.SendActivityAsync(MessageFactory.Attachment(userCard), cancellationToken).ConfigureAwait(false); } }
protected override async Task <MessagingExtensionActionResponse> OnTeamsMessagingExtensionFetchTaskAsync(ITurnContext <IInvokeActivity> turnContext, MessagingExtensionQuery query, CancellationToken cancellationToken) { return(AdaptiveCardHelper.CreateTaskModuleAdaptiveCardResponse()); }
/// <summary> /// Handle message activity in channel. /// </summary> /// <param name="message">A message in a conversation.</param> /// <param name="turnContext">Context object containing information cached for a single turn of conversation with a user.</param> /// <param name="cancellationToken">Propagates notification that operations should be canceled.</param> /// <returns>A task that represents the work queued to execute.</returns> private async Task OnMessageActivityInChannelAsync( IMessageActivity message, ITurnContext <IMessageActivity> turnContext, CancellationToken cancellationToken) { try { if (message.Value == null) { await turnContext.SendActivityAsync(this.localizer.GetString("ErrorWhenMessageInChannel")); return; } IMessageActivity userNotification = null; CompanyResponseEntity companyResponseEntity = null; var cardPostedData = ((JObject)message.Value).ToObject <AdaptiveSubmitActionData>(); var text = cardPostedData.AdaptiveCardActions.Text; var activity = turnContext.Activity; switch (text) { case Constants.ApproveCommand: if (string.IsNullOrEmpty(cardPostedData.UpdatedQuestionCategory) || string.IsNullOrEmpty(cardPostedData.UpdatedQuestionText) || string.IsNullOrEmpty(cardPostedData.UpdatedResponseText)) { companyResponseEntity = this.companyResponseStorageProvider.GetCompanyResponseEntityAsync(cardPostedData.ResponseId).GetAwaiter().GetResult(); var attachment = AdminCard.GetNewResponseRequestCard(companyResponseEntity, localizer: this.localizer, emptyApproveField: true); await AdaptiveCardHelper.RefreshCardAsync(turnContext, companyResponseEntity.ActivityId, attachment); return; } companyResponseEntity = this.companyStorageHelper.AddApprovedData(cardPostedData, activity.From.Name, activity.From.AadObjectId); var approveRequestResult = this.companyResponseStorageProvider.UpsertConverationStateAsync(companyResponseEntity).GetAwaiter().GetResult(); if (approveRequestResult) { // Refresh the approved card in channel. var attachment = AdminCard.GetRefreshedCardForApprovedRequest(companyResponseEntity, activity.From.Name, localizer: this.localizer); await AdaptiveCardHelper.RefreshCardAsync(turnContext, companyResponseEntity.ActivityId, attachment); // Get user notification attachment and send it to user for approved request. userNotification = MessageFactory.Attachment(UserCard.GetNotificationCardForApprovedRequest(companyResponseEntity, localizer: this.localizer)); var result = await this.conversationStorageProvider.GetConversationEntityAsync(companyResponseEntity.UserId); if (result != null) { await AdaptiveCardHelper.SendNotificationCardAsync(turnContext, userNotification, result.ConversationId, cancellationToken); // Tracking for number of requests approved. this.RecordEvent(ApprovedRequestEventName, turnContext); } else { this.logger.LogInformation("Unable to send notification card for approved request because conversation id is null."); } } else { this.logger.LogInformation("Unable to approve the request."); } break; case Constants.RejectCommand: companyResponseEntity = this.companyStorageHelper.AddRejectedData(cardPostedData, activity.From.Name, activity.From.AadObjectId); var rejectRequestResult = this.companyResponseStorageProvider.UpsertConverationStateAsync(companyResponseEntity).GetAwaiter().GetResult(); if (rejectRequestResult) { // Get user notification rejected card attachment. var attachment = AdminCard.GetRefreshedCardForRejectedRequest(companyResponseEntity, activity.From.Name, localizer: this.localizer); await AdaptiveCardHelper.RefreshCardAsync(turnContext, companyResponseEntity.ActivityId, attachment); // Send end user notification for approved request. userNotification = MessageFactory.Attachment(UserCard.GetNotificationCardForRejectedRequest(companyResponseEntity, localizer: this.localizer)); var result = await this.conversationStorageProvider.GetConversationEntityAsync(companyResponseEntity.UserId); if (result != null) { await AdaptiveCardHelper.SendNotificationCardAsync(turnContext, userNotification, result.ConversationId, cancellationToken); // Tracking for number of requests rejected. this.RecordEvent(RejectedRequestEventName, turnContext); } else { this.logger.LogInformation("Unable to send notification card for rejected request because conversation id is null."); } } else { this.logger.LogInformation("Unable to reject the request."); } return; default: this.logger.LogInformation("Unrecognized input in channel"); break; } } catch (Exception ex) { this.logger.LogError(ex, $"Error processing message: {ex.Message}", SeverityLevel.Error); throw; } }
/// <summary> /// Handle adaptive card submit in 1:1 chat. /// Submits the question or feedback to the SME team. /// </summary> /// <param name="message">A message in a conversation.</param> /// <param name="turnContext">Context object containing information cached for a single turn of conversation with a user.</param> /// <param name="cancellationToken">Propagates notification that operations should be canceled.</param> /// <returns>A task that represents the work queued to execute.</returns> public async Task SendAdaptiveCardInPersonalChatAsync( IMessageActivity message, ITurnContext <IMessageActivity> turnContext, CancellationToken cancellationToken) { Attachment smeTeamCard = null; // Notification to SME team Attachment userCard = null; // Acknowledgement to the user TicketEntity newTicket = null; // New ticket string text = (message.Text ?? string.Empty).Trim(); switch (text) { // Sends user ask an expert card from the answer card. case Constants.AskAnExpert: this.logger.LogInformation("Sending user ask an expert card (from answer)"); var askAnExpertPayload = ((JObject)message.Value).ToObject <ResponseCardPayload>(); await this.SendActivityInChatAsync(turnContext, MessageFactory.Attachment(AskAnExpertCard.GetCard(askAnExpertPayload)), cancellationToken); break; // Sends user the feedback card from the answer card. case Constants.ShareFeedback: this.logger.LogInformation("Sending user share feedback card (from answer)"); var shareFeedbackPayload = ((JObject)message.Value).ToObject <ResponseCardPayload>(); await this.SendActivityInChatAsync(turnContext, MessageFactory.Attachment(ShareFeedbackCard.GetCard(shareFeedbackPayload)), cancellationToken); break; // User submits the ask an expert card. case Constants.AskAnExpertSubmitText: this.logger.LogInformation("Received question for expert"); newTicket = await AdaptiveCardHelper.AskAnExpertSubmitText(message, turnContext, cancellationToken, this.ticketsProvider).ConfigureAwait(false); if (newTicket != null) { smeTeamCard = new SmeTicketCard(newTicket).ToAttachment(); userCard = new UserNotificationCard(newTicket).ToAttachment(Strings.NotificationCardContent); } break; // User submits the share feedback card. case Constants.ShareFeedbackSubmitText: this.logger.LogInformation("Received app feedback"); smeTeamCard = await AdaptiveCardHelper.ShareFeedbackSubmitText(message, turnContext, cancellationToken).ConfigureAwait(false); if (smeTeamCard != null) { await this.SendActivityInChatAsync(turnContext, MessageFactory.Text(Strings.ThankYouTextContent), cancellationToken); } break; default: var payload = ((JObject)message.Value).ToObject <ResponseCardPayload>(); if (payload.IsPrompt) { this.logger.LogInformation("Sending input to QnAMaker for prompt"); await this.qnaPairServiceFacade.GetReplyToQnAAsync(turnContext, message).ConfigureAwait(false); } else { this.logger.LogWarning($"Unexpected text in submit payload: {message.Text}"); } break; } string expertTeamId = await this.configurationProvider.GetSavedEntityDetailAsync(ConfigurationEntityTypes.TeamId).ConfigureAwait(false); // Send message to SME team. if (smeTeamCard != null) { await this.SendTicketCardToSMETeamAsync(turnContext, smeTeamCard, expertTeamId, cancellationToken, newTicket); } // Send acknowledgment to the user if (userCard != null) { await this.SendActivityInChatAsync(turnContext, MessageFactory.Attachment(userCard), cancellationToken); } }
// 1. Will be called when user triggers messaging extension which then calls CreateTaskModuleCommand protected override async Task <MessagingExtensionActionResponse> OnTeamsMessagingExtensionFetchTaskAsync(ITurnContext <IInvokeActivity> turnContext, MessagingExtensionAction action, CancellationToken cancellationToken) { // Check if the bot has been installed in the team by getting the team rooster try { var teamsMembers = await TeamsInfo.GetMembersAsync(turnContext); } catch { // if not installed we will send out the card instructing the user to install the bot string jitCardPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Cards", "jitCard.json"); var jitCard = File.ReadAllText(jitCardPath, Encoding.UTF8); string jitCardJson = jitCard; var jitCardTeams = AdaptiveCard.FromJson(jitCardJson); return(await Task.FromResult(new MessagingExtensionActionResponse { Task = new TaskModuleContinueResponse { Value = new TaskModuleTaskInfo { Card = new Attachment { Content = jitCardTeams.Card, ContentType = AdaptiveCard.ContentType, }, Height = 300, Width = 600, Title = "Install bot", }, }, })); } var magicCode = string.Empty; var state = (turnContext.Activity.Value as Newtonsoft.Json.Linq.JObject).Value <string>("state"); if (!string.IsNullOrEmpty(state)) { int parsed = 0; if (int.TryParse(state, out parsed)) { magicCode = parsed.ToString(); } } var tokenResponse = await(turnContext.Adapter as IUserTokenProvider).GetUserTokenAsync(turnContext, _connectionName, magicCode, cancellationToken: cancellationToken); if (tokenResponse == null || string.IsNullOrEmpty(tokenResponse.Token)) { // There is no token, so the user has not signed in yet. // Retrieve the OAuth Sign in Link to use in the MessagingExtensionResult Suggested Actions var signInLink = await(turnContext.Adapter as IUserTokenProvider).GetOauthSignInLinkAsync(turnContext, _connectionName, cancellationToken); return(new MessagingExtensionActionResponse { ComposeExtension = new MessagingExtensionResult { Type = "auth", SuggestedActions = new MessagingExtensionSuggestedAction { Actions = new List <CardAction> { new CardAction { Type = ActionTypes.OpenUrl, Value = signInLink, Title = "Sign in Please", }, }, }, }, }); } var accessToken = tokenResponse.Token; if (accessToken != null || !string.IsNullOrEmpty(accessToken)) { // Create Graph Client var client = new SimpleGraphClient(accessToken); // Get Group details var channel = turnContext.Activity.TeamsGetChannelId(); if (channel != null) { var members = new List <TeamsChannelAccount>(); string continuationToken = null; do { var currentPage = await TeamsInfo.GetPagedMembersAsync(turnContext, 100, continuationToken, cancellationToken); continuationToken = currentPage.ContinuationToken; members = members.Concat(currentPage.Members).ToList(); }while (continuationToken != null); TeamDetails teamDetails = await TeamsInfo.GetTeamDetailsAsync(turnContext, turnContext.Activity.TeamsGetTeamInfo().Id, cancellationToken); if (teamDetails != null) { var groupId = teamDetails.AadGroupId; plannerGroupId = groupId; //Get Plans var currentGroupPlan = await client.GetCurrentPlan(groupId); var favoritePlans = await client.GetFavoritePlans(); // Fill Adaptive Card data var exampleData = new ExampleData(); exampleData.MultiSelect = "false"; if (currentGroupPlan.CurrentPage.Count == 0) { exampleData.Option1 = favoritePlans.CurrentPage[4].Title; exampleData.Option1Value = favoritePlans.CurrentPage[4].Id; } else { exampleData.Option1 = currentGroupPlan.CurrentPage[0].Title; exampleData.Option1Value = currentGroupPlan.CurrentPage[0].Id; } exampleData.Option2 = favoritePlans.CurrentPage[0].Title; exampleData.Option3 = favoritePlans.CurrentPage[1].Title; exampleData.Option4 = favoritePlans.CurrentPage[2].Title; exampleData.Option2Value = favoritePlans.CurrentPage[0].Id; exampleData.Option3Value = favoritePlans.CurrentPage[1].Id; exampleData.Option4Value = favoritePlans.CurrentPage[2].Id; // Create and return card var adaptiveCardEditor = AdaptiveCardHelper.CreateAdaptiveCardEditor(exampleData); //var adaptiveCardEditor = CreateAdaptiveCard(); return(await Task.FromResult(new MessagingExtensionActionResponse { Task = new TaskModuleContinueResponse { Value = new TaskModuleTaskInfo { Card = new Microsoft.Bot.Schema.Attachment { Content = adaptiveCardEditor, ContentType = AdaptiveCard.ContentType, }, Height = 600, Width = 600, Title = "Task creation", }, }, })); } } else { // Return only favorite plans without current plan as in 1:1 or group chat var favoritePlans = await client.GetFavoritePlans(); // Fill Adaptive Card data var exampleData = new ExampleData(); exampleData.MultiSelect = "false"; exampleData.Option1 = favoritePlans.CurrentPage[0].Title; exampleData.Option2 = favoritePlans.CurrentPage[1].Title; exampleData.Option3 = favoritePlans.CurrentPage[2].Title; exampleData.Option1Value = favoritePlans.CurrentPage[0].Id; exampleData.Option3Value = favoritePlans.CurrentPage[1].Id; exampleData.Option4Value = favoritePlans.CurrentPage[2].Id; // Create and return card var adaptiveCardEditor = AdaptiveCardHelper.CreateAdaptiveCardEditor(exampleData); //var adaptiveCardEditor = CreateAdaptiveCard(); return(await Task.FromResult(new MessagingExtensionActionResponse { Task = new TaskModuleContinueResponse { Value = new TaskModuleTaskInfo { Card = new Microsoft.Bot.Schema.Attachment { Content = adaptiveCardEditor, ContentType = AdaptiveCard.ContentType, }, Height = 600, Width = 600, Title = "Task creation", }, }, })); } } //Needs to be replaced with OAuth Prompt return(null); }
private async Task HandleUnrecognizedMsgInOneOnOneChat(ConnectorClient connectorClient, Activity activity, string tenantId, ChannelAccount sender) { // We either display a welcome user message or a simple unrecognized message. // Both will list all the actions you can do and admin actions if the user is an admin. // 1. Determine the team context. // 2. If we don't have just one, ask for which team to perform actions for // 3. Show welcome user if the user has not joined that team // 4. Show unrecognized message if the user has joined that team before. TeamContext teamForActions = null; // Try to get it from the message if this was from the welcome team "Chat with me" action. var teamIdFromWelcomeTeam = AdaptiveCardHelper.GetTeamIdFromChatWithMeMessage(activity.Text); if (!string.IsNullOrEmpty(teamIdFromWelcomeTeam)) { string teamName = await this.bot.GetTeamNameAsync(connectorClient, teamIdFromWelcomeTeam); teamForActions = new TeamContext { TeamId = teamIdFromWelcomeTeam, TeamName = teamName }; } else { // Extract it from the ChooseTeamHeroCard response var userAndTeam = ActivityHelper.GetUserAndTeam(activity, sender.GetUserId(), sender.Name); teamForActions = userAndTeam?.Team; } if (teamForActions == null) { var allTeams = await this.bot.GetAllTeams(connectorClient); if (allTeams.Count > 1) { var chooseTeamCard = ChooseTeamHeroCard.GetCard(Resources.UnrecognizedInputChooseTeam, allTeams, actionMessage: activity.Text); await ActivityHelper.ReplyWithHeroCard(connectorClient, activity, chooseTeamCard); return; } if (allTeams.Count == 0) { await connectorClient.Conversations.ReplyToActivityAsync(activity.CreateReply(Resources.UnrecognizedInputNoTeam)); return; } teamForActions = allTeams.First(); } var userInfo = await this.bot.GetOrCreateUnpersistedUserInfo(tenantId, sender.GetUserId()); var userStatus = userInfo.GetStatusInTeam(teamForActions.TeamId); var isUserAdminOfTeam = userInfo.AdminForTeams.Contains(teamForActions.TeamId); if (userStatus == EnrollmentStatus.NotJoined) { await this.bot.WelcomeUser(connectorClient, sender, tenantId, teamForActions, userStatus, botInstallerName : string.Empty, isUserAdminOfTeam); } else { await this.bot.SendUnrecognizedOneOnOneMessage(connectorClient, activity.CreateReply(), teamForActions, userStatus, isUserAdminOfTeam); } }