/// <summary> /// This method will construct the share feedback notification card for admin team. /// </summary> /// <param name="feedbackData">User activity payload.</param> /// <param name="userDetails">User details.</param> /// <returns>Share feedback notification card attachment.</returns> public Attachment GetShareFeedbackNotificationCard(SubmitActionDataForTeamsBehavior feedbackData, TeamsChannelAccount userDetails) { this.logger.LogInformation("Get share feedback notification card initiated."); var shareFeedbackCardContents = new ShareFeedbackCardData() { FeedbackText = this.localizer.GetString("Feedback"), FeedbackSubHeaderText = this.localizer.GetString("FeedbackSubHeaderText", userDetails.GivenName), FeedbackType = feedbackData.FeedbackType, DescriptionText = this.localizer.GetString("FeedbackDescriptionTitleText"), FeedbackDescription = feedbackData.FeedbackDescription, CreatedOnText = this.localizer.GetString("CreatedOn"), FeedbackCreatedDate = DateTime.UtcNow.ToShortDateString(), ChatWithUserButtonText = this.localizer.GetString("ChatWithMatchButtonText", userDetails.GivenName), ChatInitiateURL = new Uri($"{Constants.ChatInitiateURL}?users={Uri.EscapeDataString(userDetails.UserPrincipalName)}&message={Uri.EscapeDataString(Strings.InitiateChatText)}").ToString(), }; var cardTemplate = this.GetCardTemplate(CardCacheConstants.ShareFeedbackJsonTemplate, ShareFeedbackCardFileName); var template = new AdaptiveCardTemplate(cardTemplate); var card = template.Expand(shareFeedbackCardContents); Attachment attachment = new Attachment() { ContentType = AdaptiveCard.ContentType, Content = AdaptiveCard.FromJson(card).Card, }; this.logger.LogInformation("Get share feedback notification card succeeded."); return(attachment); }
/// <summary> /// Handle when a message is addressed to the bot. /// </summary> /// <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 resolving to either a login card or the adaptive card of the Reddit post.</returns> /// <remarks> /// For more information on bot messaging in Teams, see the documentation /// https://docs.microsoft.com/en-us/microsoftteams/platform/bots/how-to/conversations/conversation-basics?tabs=dotnet#receive-a-message . /// </remarks> protected override async Task OnMessageActivityAsync(ITurnContext <IMessageActivity> turnContext, CancellationToken cancellationToken) { turnContext = turnContext ?? throw new ArgumentNullException(nameof(turnContext)); var activity = turnContext.Activity; try { string command; SubmitActionDataForTeamsBehavior valuesFromCard = null; if (string.IsNullOrWhiteSpace(activity.Text) && JObject.Parse(activity.Value?.ToString())["command"].ToString() == null) { return; } // We are supporting pause/resume matches either from bot command or Adaptive submit card action. if (string.IsNullOrWhiteSpace(activity.Text) && activity.Value != null) { valuesFromCard = ((JObject)activity.Value).ToObject <SubmitActionDataForTeamsBehavior>(); command = valuesFromCard.Command.Trim(); } else { command = activity.Text.Trim(); } if (activity.Conversation.ConversationType == PersonalConversationType) { // Command to get configure pair-up matches notification card. if (command.Equals(this.localizer.GetString("PauseMatchesCommand"), StringComparison.CurrentCultureIgnoreCase) || command == Constants.PauseMatchesCommand) { if (activity.Value == null) { // Send user matches card. await this.userTeamMappingsHelper.SendUserTeamMappingsCardAsync(turnContext, cancellationToken); return; } if (valuesFromCard.TeamId != null) { var userPairUpMappingEntity = await this.teamUserPairUpMappingRepository.GetAsync(activity.From.AadObjectId, valuesFromCard.TeamId); userPairUpMappingEntity.IsPaused = true; await this.teamUserPairUpMappingRepository.InsertOrMergeAsync(userPairUpMappingEntity); var configureUserMatchesNoticationCard = MessageFactory.Attachment(this.cardHelper.GetConfigureMatchesNotificationCard()); await turnContext.SendActivityAsync(configureUserMatchesNoticationCard, cancellationToken); return; } } // Command to get user matches card. else if (command.Equals(this.localizer.GetString("ConfigureMatchesCommand"), StringComparison.CurrentCultureIgnoreCase) || command == Constants.ConfigureMatchesCommand) { await this.userTeamMappingsHelper.SendUserTeamMappingsCardAsync(turnContext, cancellationToken); return; } // Command to update user pair-ups. else if (command.Equals(this.localizer.GetString("UpdateMatchesCommand"), StringComparison.CurrentCultureIgnoreCase) || command == Constants.UpdateMatchesCommand) { if (activity.Value == null) { // Send user matches card. await this.userTeamMappingsHelper.SendUserTeamMappingsCardAsync(turnContext, cancellationToken); return; } // Adaptive card submit action sends back only team id's which are being checked. // Explicitly setting choice set as empty array of string when all the choices are unchecked, // to update the IsPaused flag as 'false' for all the teams where user is a member. var choiceSet = JObject.Parse(activity.Value.ToString())["choiceset"] != null ? JObject.Parse(activity.Value?.ToString())["choiceset"].ToString().Split(",") : new string[0]; var userTeamMappings = await this.teamUserPairUpMappingRepository.GetAllAsync(activity.From.AadObjectId); foreach (var teamUserPair in userTeamMappings) { teamUserPair.IsPaused = choiceSet.Contains(teamUserPair.TeamId); await this.teamUserPairUpMappingRepository.InsertOrMergeAsync(teamUserPair); } var updateConfigurePairupCard = MessageFactory.Attachment(this.cardHelper.GetResumePairupNotificationCard()); await turnContext.SendActivityAsync(updateConfigurePairupCard, cancellationToken); return; } else if (command == Constants.ShareCommand) { if (valuesFromCard != null && !string.IsNullOrWhiteSpace(valuesFromCard.FeedbackDescription) && !string.IsNullOrWhiteSpace(valuesFromCard.FeedbackType)) { TeamsChannelAccount userDetails = await this.GetConversationUserDetailAsync(turnContext, cancellationToken); var teamNotificationAttachment = this.cardHelper.GetShareFeedbackNotificationCard(valuesFromCard, userDetails); var feedbackEntity = new FeedbackEntity { Feedback = valuesFromCard.FeedbackDescription, FeedbackId = Guid.NewGuid().ToString(), UserAadObjectId = userDetails.AadObjectId, SubmittedOn = DateTime.UtcNow, }; this.logger.LogInformation("Feedback submitted successfully"); await this.notificationCardHelper.SendProactiveNotificationCardAsync(teamNotificationAttachment, this.botOptions.Value.AdminTeamId, activity.ServiceUrl); await turnContext.SendActivityAsync(this.localizer.GetString("FeedbackSubmittedMessage")); await this.feedbackDataRepository.InsertOrMergeAsync(feedbackEntity); } } else { await this.knowledgeBaseResponse.SendReplyToQuestionAsync(turnContext, activity.Text); } } else if (activity.Conversation.ConversationType == ChannelConversationType) { if (activity.Value != null) { await this.teamNotification.UpdateGroupApprovalNotificationAsync(turnContext); } else { // Send help card for unsupported bot command. await turnContext.SendActivityAsync(this.localizer.GetString("UnSupportedBotCommand")); return; } } } catch (Exception ex) { this.logger.LogError($"Error while processing message request. {ex.Message}"); await turnContext.SendActivityAsync(this.localizer.GetString("ErrorMessage")); return; } }