private async Task HandleChannelConversation(IDialogContext context, Microsoft.Bot.Connector.Activity activity) { var connector = new ConnectorClient(new Uri(activity.ServiceUrl)); // Channel conversation // Get the question text, and team and channel details var question = activity.Text; var messageId = activity.Id; var conversationId = activity.Conversation.Id; var channelData = activity.GetChannelData <TeamsChannelData>(); string tenantId = channelData.Tenant.Id; string teamId = channelData.Team.Id; string channelId = channelData.Channel.Id; TeamDetails teamDetails = connector.GetTeamsConnectorClient().Teams.FetchTeamDetails(teamId); var teamName = teamDetails.Name; var groupId = teamDetails.AadGroupId; ConversationList channelList = connector.GetTeamsConnectorClient().Teams.FetchChannelList(teamId); var channel = channelList.Conversations.Where(x => x.Id == channelId).FirstOrDefault(); var channelName = channel?.Name; var topic = channelName ?? "General"; IList <ChannelAccount> members = await connector.Conversations.GetConversationMembersAsync(teamId); var teamsMembers = members.AsTeamsChannelAccounts(); // Get original poster var originalPosterAsTeamsChannelAccount = teamsMembers.Where(x => x.ObjectId == activity.From.Properties["aadObjectId"].ToString()).FirstOrDefault(); var userUpn = originalPosterAsTeamsChannelAccount.UserPrincipalName; var user = SQLService.GetUser(userUpn); // strip @bot mention for teams if (activity.ChannelId == "msteams") { activity = MicrosoftTeamsChannelHelper.StripAtMentionText(activity); } else { activity.Text = activity.Text.Trim(); } // strip the html tags question = MicrosoftTeamsChannelHelper.StripHtmlTags(activity.Text); var questionModel = new QuestionModel() { ID = 0, TenantId = tenantId, GroupId = groupId, TeamId = teamId, TeamName = teamName, ConversationId = conversationId, MessageId = messageId, Topic = topic, QuestionText = question, QuestionSubmitted = DateTime.Now, OriginalPoster = user, Link = CreateLink(conversationId, tenantId, groupId, messageId, teamName, topic), }; if (string.IsNullOrEmpty(question)) { await HandleNoQuestion(context, activity, questionModel, channelId); } else { // get courseID var courseID = SQLService.GetCourseIDByName(teamName.Trim()); var course = SQLService.GetCourse(courseID); questionModel.CourseID = courseID; await HandleQuestionWorkflow(context, activity, course, questionModel); } }
private async Task HandleBotHelpful(Microsoft.Bot.Connector.Activity activity) { ConnectorClient connector = new ConnectorClient(new Uri(activity.ServiceUrl)); // Question has been answered // store answer in db. // get question details int questionId = Convert.ToInt32((activity.Value as dynamic)["questionId"]); string answer = (activity.Value as dynamic)["answer"]; int answerId = Convert.ToInt32((activity.Value as dynamic)["qnaId"]); var question = SQLService.GetQuestion(questionId); // get user details var channelData = activity.GetChannelData <Microsoft.Bot.Connector.Teams.Models.TeamsChannelData>(); var members = await connector.Conversations.GetConversationMembersAsync(channelData.Team.Id); var teamsMembers = members.AsTeamsChannelAccounts(); var currentUser = teamsMembers.Where(x => x.ObjectId == activity.From.Properties["aadObjectId"].ToString()).FirstOrDefault(); var studentUPN = currentUser.UserPrincipalName; var isUserAdmin = SQLService.IsUserAdmin(studentUPN); // store question in qna string teamId = channelData.Team.Id; TeamDetails teamDetails; try { teamDetails = connector.GetTeamsConnectorClient().Teams.FetchTeamDetails(teamId); } catch (Exception e) { teamDetails = connector.GetTeamsConnectorClient().Teams.FetchTeamDetails(teamId); Trace.TraceError(e.ToString()); } var teamName = teamDetails.Name; var courseID = SQLService.GetCourseIDByName(teamName.Trim()); // check if user can set question status if (isUserAdmin || (studentUPN == question.OriginalPoster.Email) || (studentUPN == question.OriginalPoster.UserName)) // double check question to course? not sure { var answeredBy = SQLService.GetBotUser(courseID); // update question model question.QuestionStatus = Constants.QUESTION_STATUS_ANSWERED; question.QuestionAnswered = DateTime.Now; question.AnswerText = answer; question.AnswerPoster = answeredBy; SQLService.CreateOrUpdateQuestion(question); // update old activity Microsoft.Bot.Connector.Activity updatedReply = activity.CreateReply(); var card = new AdaptiveCard(); var answerBlock = new AdaptiveTextBlock("Answer: " + question.AnswerText.ReplaceLinksWithMarkdown()); answerBlock.Weight = AdaptiveTextWeight.Bolder; answerBlock.Size = AdaptiveTextSize.Medium; answerBlock.Wrap = true; var markedBlock = new AdaptiveTextBlock($"Marked as " + question.QuestionStatus + " by " + currentUser.Name); markedBlock.Wrap = true; var answeredBlock = new AdaptiveTextBlock("Answered by: " + question.AnswerPoster.FullName); answeredBlock.Weight = AdaptiveTextWeight.Bolder; answeredBlock.Wrap = true; card.Body.Add(answerBlock); card.Body.Add(answeredBlock); card.Body.Add(markedBlock); Attachment attachment = new Attachment() { ContentType = AdaptiveCard.ContentType, Content = card, }; updatedReply.Attachments.Add(attachment); await connector.Conversations.UpdateActivityAsync(activity.Conversation.Id, activity.ReplyToId, updatedReply); var predictiveQnAService = new PredictiveQnAService(courseID); var res = await predictiveQnAService.UpdateQnAPair(new List <string> { question.QuestionText }, null, answer, answerId); } }
private async Task <HttpResponseMessage> HandleSelectAnswerFromMessageAction(Microsoft.Bot.Connector.Activity activity) { ConnectorClient connector = new ConnectorClient(new Uri(activity.ServiceUrl)); TeamsMessage selectedReply = JsonConvert.DeserializeObject <TeamsMessage>(JsonConvert.SerializeObject((activity.Value as dynamic)["messagePayload"])); if (selectedReply.From.User == null) { return(Request.CreateResponse(HttpStatusCode.OK)); } var question = SQLService.GetQuestionByMessageId(selectedReply.ReplyToId); if (question == null) { return(Request.CreateResponse(HttpStatusCode.OK)); } // get user details var channelData = activity.GetChannelData <Microsoft.Bot.Connector.Teams.Models.TeamsChannelData>(); var members = await connector.Conversations.GetConversationMembersAsync(channelData.Team.Id); var teamsMembers = members.AsTeamsChannelAccounts(); var currentUser = teamsMembers.Where(x => x.ObjectId == activity.From.Properties["aadObjectId"].ToString()).FirstOrDefault(); var studentUPN = currentUser.UserPrincipalName; var isUserAdmin = SQLService.IsUserAdmin(studentUPN); // check if user can set question status if (isUserAdmin || (studentUPN == question.OriginalPoster.Email) || (studentUPN == question.OriginalPoster.UserName)) { var selectedReplyUser = teamsMembers.Where(x => x.ObjectId == selectedReply.From.User.Id).FirstOrDefault(); var answeredBy = SQLService.GetUser(selectedReplyUser.UserPrincipalName); // update question model question.QuestionStatus = Constants.QUESTION_STATUS_ANSWERED; question.QuestionAnswered = DateTime.Now; question.AnswerText = MicrosoftTeamsChannelHelper.StripMentionAndHtml(selectedReply.Body.Content); question.AnswerPoster = answeredBy; SQLService.CreateOrUpdateQuestion(question); Microsoft.Bot.Connector.Activity updatedReply = activity.CreateReply(); var card = new AdaptiveCard(); var answerBlock = new AdaptiveTextBlock("Answer: " + question.AnswerText.ReplaceLinksWithMarkdown()); answerBlock.Weight = AdaptiveTextWeight.Bolder; answerBlock.Size = AdaptiveTextSize.Medium; answerBlock.Wrap = true; var markedBlock = new AdaptiveTextBlock($"Marked as " + question.QuestionStatus + " by " + currentUser.Name); markedBlock.Wrap = true; var answeredBlock = new AdaptiveTextBlock("Answered by: " + question.AnswerPoster.FullName); answeredBlock.Weight = AdaptiveTextWeight.Bolder; answeredBlock.Wrap = true; card.Body.Add(answerBlock); card.Body.Add(answeredBlock); card.Body.Add(markedBlock); Attachment attachment = new Attachment() { ContentType = AdaptiveCard.ContentType, Content = card, }; updatedReply.Attachments.Add(attachment); if (question.AnswerCardActivityId == null) { var r = await connector.Conversations.ReplyToActivityAsync(updatedReply.Conversation.Id, updatedReply.ReplyToId, updatedReply); question.AnswerCardActivityId = r.Id; SQLService.CreateOrUpdateQuestion(question); } else { updatedReply.ReplyToId = question.AnswerCardActivityId; var r = await connector.Conversations.UpdateActivityAsync(updatedReply.Conversation.Id, updatedReply.ReplyToId, updatedReply); question.AnswerCardActivityId = r.Id; SQLService.CreateOrUpdateQuestion(question); } } var baseUrl = ServiceHelper.BaseUrl; var taskInfo = new Models.TaskInfo(); taskInfo.Title = "Select Answer"; taskInfo.Height = 300; taskInfo.Width = 400; taskInfo.Url = baseUrl + @"/home/selectanswer?json=" + "Answer Updated"; Models.TaskEnvelope taskEnvelope = new Models.TaskEnvelope { Task = new Models.Task() { Type = Models.TaskType.Continue, TaskInfo = taskInfo, }, }; return(Request.CreateResponse(HttpStatusCode.OK, taskEnvelope)); }
private async Task HandleMarkedAnswerFromCard(Microsoft.Bot.Connector.Activity activity) { ConnectorClient connector = new ConnectorClient(new Uri(activity.ServiceUrl)); // Handle answer payload var adaptiveCardAnswerJson = activity.Value.ToString(); var adaptiveCardAnswer = JsonConvert.DeserializeObject <AdaptiveCardAnswerSubmit>(adaptiveCardAnswerJson); string selectedReplyJson = adaptiveCardAnswer.Answer; string questionId = adaptiveCardAnswer.QuestionId; if (string.IsNullOrEmpty(selectedReplyJson)) { Microsoft.Bot.Connector.Activity newReply = activity.CreateReply(); newReply.Text = "There seems to be an issue saving the answer."; await connector.Conversations.ReplyToActivityAsync(activity.Conversation.Id, activity.ReplyToId, newReply); } else { var selectedReply = JsonConvert.DeserializeObject <TeamsMessage>(selectedReplyJson); var question = SQLService.GetQuestion(Convert.ToInt32(questionId)); // get user details var channelData = activity.GetChannelData <Microsoft.Bot.Connector.Teams.Models.TeamsChannelData>(); var members = await connector.Conversations.GetConversationMembersAsync(channelData.Team.Id); var teamsMembers = members.AsTeamsChannelAccounts(); var currentUser = teamsMembers.Where(x => x.ObjectId == activity.From.Properties["aadObjectId"].ToString()).FirstOrDefault(); var studentUPN = currentUser.UserPrincipalName; var isUserAdmin = SQLService.IsUserAdmin(studentUPN); string teamId = channelData.Team.Id; TeamDetails teamDetails; try { teamDetails = connector.GetTeamsConnectorClient().Teams.FetchTeamDetails(teamId); } catch (Exception e) { teamDetails = connector.GetTeamsConnectorClient().Teams.FetchTeamDetails(teamId); Trace.TraceError(e.ToString()); } var teamName = teamDetails.Name; var courseID = SQLService.GetCourseIDByName(teamName.Trim()); // check if user can set question status if (isUserAdmin || (studentUPN == question.OriginalPoster.Email) || (studentUPN == question.OriginalPoster.UserName)) { var selectedReplyUser = teamsMembers.Where(x => x.ObjectId == selectedReply.From.User.Id).FirstOrDefault(); var answeredBy = SQLService.GetUser(selectedReplyUser.UserPrincipalName); // update question model question.QuestionStatus = Constants.QUESTION_STATUS_ANSWERED; question.QuestionAnswered = DateTime.Now; question.AnswerText = MicrosoftTeamsChannelHelper.StripMentionAndHtml(selectedReply.Body.Content); question.AnswerPoster = answeredBy; SQLService.CreateOrUpdateQuestion(question); // update old activity Microsoft.Bot.Connector.Activity updatedReply = activity.CreateReply(); var card = new AdaptiveCard(); var answer = new AdaptiveTextBlock("Answer: " + question.AnswerText.ReplaceLinksWithMarkdown()); answer.Weight = AdaptiveTextWeight.Bolder; answer.Size = AdaptiveTextSize.Medium; answer.Wrap = true; var marked = new AdaptiveTextBlock($"Marked as " + question.QuestionStatus + " by " + currentUser.Name); marked.Wrap = true; var answered = new AdaptiveTextBlock("Answered by: " + question.AnswerPoster.FullName); answered.Weight = AdaptiveTextWeight.Bolder; answered.Wrap = true; card.Body.Add(answer); card.Body.Add(answered); card.Body.Add(marked); Attachment attachment = new Attachment() { ContentType = AdaptiveCard.ContentType, Content = card, }; updatedReply.Attachments.Add(attachment); await connector.Conversations.UpdateActivityAsync(activity.Conversation.Id, activity.ReplyToId, updatedReply); var predictiveQnAService = new PredictiveQnAService(courseID); var res = await predictiveQnAService.AddQnAPair(question.QuestionText, question.AnswerText); } } }
private async Task HandleSelectAnswerFromCard(Microsoft.Bot.Connector.Activity activity) { ConnectorClient connector = new ConnectorClient(new Uri(activity.ServiceUrl)); // get question details int questionId = Convert.ToInt32((activity.Value as dynamic)["questionId"]); var question = SQLService.GetQuestion(questionId); // get user details var channelData = activity.GetChannelData <Microsoft.Bot.Connector.Teams.Models.TeamsChannelData>(); var members = await connector.Conversations.GetConversationMembersAsync(channelData.Team.Id); var teamsMembers = members.AsTeamsChannelAccounts(); var currentUser = teamsMembers.Where(x => x.ObjectId == activity.From.Properties["aadObjectId"].ToString()).FirstOrDefault(); var studentUPN = currentUser.UserPrincipalName; // var isUserAdmin = SharePointServices.IsUserAdmin(studentUPN); var isUserAdmin = SQLService.IsUserAdmin(studentUPN); // check if user can set question status if (isUserAdmin || (studentUPN == question.OriginalPoster.Email) || (studentUPN == question.OriginalPoster.UserName)) { // find replies string teamId = (activity.ChannelData as dynamic)["team"]["id"].ToString(); string channelId = (activity.ChannelData as dynamic)["channel"]["id"].ToString(); var conversationId = activity.Conversation.Id; string messageId = conversationId.Split('=')[1]; // update old activity Microsoft.Bot.Connector.Activity updatedReply = activity.CreateReply(); var replies = await GetAllReplies(question.GroupId, channelId, messageId); var adaptiveCardChoices = new List <AdaptiveChoice>(); if (replies != null && replies.Count > 0) { foreach (var reply in replies) { adaptiveCardChoices.Add(new AdaptiveChoice() { Title = MicrosoftTeamsChannelHelper.StripMentionAndHtml(reply.Body.Content), Value = JsonConvert.SerializeObject(reply), }); } var bodyTextBlock = new AdaptiveTextBlock() { Text = "Select an answer" }; var bodyChoice = new AdaptiveChoiceSetInput() { Id = "Answer", Style = AdaptiveChoiceInputStyle.Compact, IsMultiSelect = false, Choices = adaptiveCardChoices, }; var adaptiveCardAnswerSubmit = new AdaptiveCardAnswerSubmit(Constants.ACTIVITY_MARKED_ANSWERED, bodyChoice.Value, questionId.ToString()); var adaptiveCardAnswerString = JsonConvert.SerializeObject(adaptiveCardAnswerSubmit); var actionJson = "{\"type\":\"" + Constants.ACTIVITY_SELECT_ANSWER + "\",\"questionId\": \"" + questionId.ToString() + "\"}"; var adaptiveCard = new AdaptiveCard() { Actions = new List <AdaptiveAction>() { new AdaptiveSubmitAction() { Title = "Save", DataJson = adaptiveCardAnswerString, }, new AdaptiveSubmitAction() { Title = "Refresh", DataJson = actionJson, }, }, }; adaptiveCard.Body.Add(bodyTextBlock); adaptiveCard.Body.Add(bodyChoice); var attachment = new Attachment() { ContentType = AdaptiveCard.ContentType, Content = adaptiveCard, }; updatedReply.Attachments.Add(attachment); try { // await connector.Conversations.UpdateActivityAsync(updatedReply); updatedReply.Id = activity.ReplyToId; var response = await connector.Conversations.UpdateActivityAsync(activity.Conversation.Id, activity.ReplyToId, updatedReply); } catch (Exception e) { Trace.TraceError(e.ToString()); } } } }
private async Task HandleBotNotHelpful(Microsoft.Bot.Connector.Activity activity) { ConnectorClient connector = new ConnectorClient(new Uri(activity.ServiceUrl)); // tag demonstrators, regular workflow // get question details int questionId = Convert.ToInt32((activity.Value as dynamic)["questionId"]); var question = SQLService.GetQuestion(questionId); // get user details var channelData = activity.GetChannelData <Microsoft.Bot.Connector.Teams.Models.TeamsChannelData>(); var members = await connector.Conversations.GetConversationMembersAsync(channelData.Team.Id); var teamsMembers = members.AsTeamsChannelAccounts(); var currentUser = teamsMembers.Where(x => x.ObjectId == activity.From.Properties["aadObjectId"].ToString()).FirstOrDefault(); var studentUPN = currentUser.UserPrincipalName; var isUserAdmin = SQLService.IsUserAdmin(studentUPN); string teamId = (activity.ChannelData as dynamic)["team"]["id"].ToString(); TeamDetails teamDetails; try { teamDetails = connector.GetTeamsConnectorClient().Teams.FetchTeamDetails(teamId); } catch (Exception e) { teamDetails = connector.GetTeamsConnectorClient().Teams.FetchTeamDetails(teamId); Trace.TraceError(e.ToString()); } var teamName = teamDetails.Name; var courseID = SQLService.GetCourseIDByName(teamName.Trim()); // check if user can set question status if (isUserAdmin || (studentUPN == question.OriginalPoster.Email) || (studentUPN == question.OriginalPoster.UserName)) { // find replies string channelId = (activity.ChannelData as dynamic)["channel"]["id"].ToString(); var conversationId = activity.Conversation.Id; string messageId = conversationId.Split('=')[1]; string originalStudentUpn = (activity.Value as dynamic)["userUpn"]; var student = SQLService.GetUser(originalStudentUpn); var adminsOnTeams = new List <ChannelAccount>(); if (student != null) { if (student.Role != null && student.Role.Name != Constants.STUDENT_ROLE) { // Not a student - notify lecturer var lecturers = SQLService.GetUsersByRole(Constants.LECTURER_ROLE, courseID); foreach (var admin in lecturers) { var adminOnTeams = teamsMembers.Where(x => (x.Email == admin.Email || x.Email == admin.UserName || x.UserPrincipalName == admin.UserName || x.UserPrincipalName == admin.Email) && (x.Email != student.Email && x.Email != student.UserName && x.UserPrincipalName != student.UserName && x.UserPrincipalName != student.Email) ).FirstOrDefault(); if (adminOnTeams != null) { adminsOnTeams.Add(adminOnTeams); } } } else { // Is a student if (student.TutorialGroups != null && student.TutorialGroups.Count > 0) { // Notify demonstrator var tutorialAdmins = new List <UserCourseRoleMappingModel>(); foreach (var tutorialGroup in student.TutorialGroups) { tutorialAdmins.AddRange(SQLService.GetDemonstrators(courseID)); } if (tutorialAdmins != null) { foreach (var admin in tutorialAdmins) { var adminOnTeams = teamsMembers.Where(x => (x.Email == admin.Email || x.Email == admin.UserName || x.UserPrincipalName == admin.UserName || x.UserPrincipalName == admin.Email) && (x.Email != student.Email && x.Email != student.UserName && x.UserPrincipalName != student.UserName && x.UserPrincipalName != student.Email) ).FirstOrDefault(); if (adminOnTeams != null) { adminsOnTeams.Add(adminOnTeams); } } } } else { // student without tutorial class? var allAdmins = SQLService.GetAllAdmins(student.CourseId).Distinct(); if (allAdmins != null) { foreach (var admin in allAdmins) { var adminOnTeams = teamsMembers.Where(x => (x.Email == admin.Email || x.Email == admin.UserName || x.UserPrincipalName == admin.UserName || x.UserPrincipalName == admin.Email) && (x.Email != student.Email && x.Email != student.UserName && x.UserPrincipalName != student.UserName && x.UserPrincipalName != student.Email) ).FirstOrDefault(); if (adminOnTeams != null) { adminsOnTeams.Add(adminOnTeams); } } } } } } else { // User not in database // Notify lecturer var lecturers = SQLService.GetUsersByRole(Constants.LECTURER_ROLE, courseID); foreach (var admin in lecturers) { var adminOnTeams = teamsMembers.Where(x => (x.Email == admin.Email || x.Email == admin.UserName || x.UserPrincipalName == admin.UserName || x.UserPrincipalName == admin.Email) && (x.Email != student.Email && x.Email != student.UserName && x.UserPrincipalName != student.UserName && x.UserPrincipalName != student.Email) ).FirstOrDefault(); if (adminOnTeams != null) { adminsOnTeams.Add(adminOnTeams); } } } // update old activity Microsoft.Bot.Connector.Activity updatedReply = activity.CreateReply(); var actionJson = "{\"Type\":\"" + Constants.ACTIVITY_SELECT_ANSWER + "\",\"QuestionId\": \"" + questionId + "\"}"; var card = new HeroCard() { Text = "Sorry I couldn't answer your question, I've tagged your demonstrators.", }; updatedReply.Attachments.Add(card.ToAttachment()); try { await connector.Conversations.UpdateActivityAsync(activity.Conversation.Id, activity.ReplyToId, updatedReply); } catch (Exception e) { Trace.TraceError(e.ToString()); } // create new tagging reply Microsoft.Bot.Connector.Activity newReply = activity.CreateReply(); // Tag Admins var distinct = adminsOnTeams .GroupBy(p => p.Id) .Select(g => g.First()) .ToList(); foreach (var admin in distinct) { newReply.AddMentionToText(admin, MentionTextLocation.AppendText); } var newActionJson = "{\"type\":\"" + Constants.ACTIVITY_SELECT_ANSWER + "\",\"questionId\": \"" + questionId + "\"}"; var newCard = new HeroCard() { Buttons = new List <CardAction>() { new CardAction(ActivityTypes.Invoke, "Select an answer", value: newActionJson), }, }; newReply.Attachments.Add(newCard.ToAttachment()); try { var response = await connector.Conversations.ReplyToActivityAsync(activity.Conversation.Id, activity.ReplyToId, newReply); } catch (Exception e) { Trace.TraceError(e.ToString()); } } }