/// <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.Type.Equals(ActivityTypes.Message, StringComparison.OrdinalIgnoreCase)) { string actionType = message.Value != null?JObject.Parse(message.Value.ToString())["AdaptiveActionType"]?.ToString() : null; string scrumMembers = message.Value != null?JObject.Parse(message.Value.ToString())["ScrumMembers"]?.ToString() : null; message.RemoveRecipientMention(); string text = string.IsNullOrEmpty(message.Text) ? actionType : message.Text; switch (text.ToUpperInvariant().Trim()) { case Constants.EndScrum: string conversationId = message.Conversation.Id; string scrumMasterId = JObject.Parse(message.Value.ToString())["ScrumMasterId"].ToString(); var scrumInfo = await this.scrumHelper.GetActiveScrumAsync(scrumMasterId); var activitySummary = await this.activityHelper.GetEndScrumSummaryActivityAsync(scrumInfo, conversationId, scrumMembers, turnContext, cancellationToken); if (activitySummary != null) { this.logger.LogInformation($"Scrum completed by: {turnContext.Activity.From.Name} for {conversationId} with ScrumStartCardResponseId: {scrumInfo.ScrumStartCardResponseId}"); await turnContext.UpdateActivityAsync(activitySummary, cancellationToken); await turnContext.SendActivityAsync(this.localizer.GetString("SuccessMessageAfterEndingScrum"), cancellationToken : cancellationToken); } break; case Constants.Help: this.logger.LogInformation("Sending help card"); var helpAttachment = HelpCard.GetHelpCard(this.localizer); await turnContext.SendActivityAsync(MessageFactory.Attachment(helpAttachment), cancellationToken); break; case Constants.Settings: this.logger.LogInformation("Sending settings button card"); var settingsAttachment = SettingsCard.GetSettingsCard(this.localizer); await turnContext.SendActivityAsync(MessageFactory.Attachment(settingsAttachment), cancellationToken); break; default: this.logger.LogInformation("Invalid command text entered in channel. Sending help card"); var helpAttachmentcard = HelpCard.GetHelpCard(this.localizer); await turnContext.SendActivityAsync(MessageFactory.Attachment(helpAttachmentcard), cancellationToken); break; } } else { await turnContext.SendActivityAsync(this.localizer.GetString("InformationAboutBotInstallationLimitation"), cancellationToken : cancellationToken); } } catch (Exception ex) { await turnContext.SendActivityAsync(this.localizer.GetString("ErrorMessage"), cancellationToken : cancellationToken); this.logger.LogError(ex, $"Error processing message: {ex.Message}", SeverityLevel.Error); } }
/// <inheritdoc/> protected override async Task OnMessageActivityAsync(ITurnContext <IMessageActivity> turnContext, CancellationToken cancellationToken) { try { await this.SendTypingIndicatorAsync(turnContext); var conversationType = turnContext.Activity.Conversation.ConversationType; string conversationId = turnContext.Activity.Conversation.Id; if (string.Compare(conversationType, "groupChat", StringComparison.OrdinalIgnoreCase) == 0) { if (turnContext.Activity.Type.Equals(ActivityTypes.Message)) { turnContext.Activity.RemoveRecipientMention(); switch (turnContext.Activity.Text.Trim().ToLower()) { case Constants.Start: this.telemetryClient.TrackTrace($"scrum {conversationId} started by {turnContext.Activity.From.Id}"); var scrum = await this.scrumProvider.GetScrumAsync(conversationId); if (scrum != null && scrum.IsScrumRunning) { // check if member in scrum exists. // A user is added during a running scrum and tries to start a new scrum. var activityId = this.GetActivityIdToMatch(scrum.MembersActivityIdMap, turnContext.Activity.From.Id); if (activityId == null) { await turnContext.SendActivityAsync(string.Format(Resources.NoPartOfScrumStartText, turnContext.Activity.From.Name)); this.telemetryClient.TrackTrace($"Member who is updating the scrum is not the part of scrum for : {conversationId}"); } else { this.telemetryClient.TrackTrace($"Scrum is already running for conversation id {conversationId}"); await turnContext.SendActivityAsync(Resources.RunningScrumMessage); } } else { // start a new scrum this.telemetryClient.TrackTrace($"Scrum start for : {conversationId}"); await this.StartScrumAsync(turnContext, cancellationToken); } break; case Constants.TakeATour: var tourCards = TourCard.GetTourCards(this.configuration["AppBaseURL"]); await turnContext.SendActivityAsync(MessageFactory.Carousel(tourCards)); break; case Constants.CompleteScrum: var scrumInfo = await this.scrumProvider.GetScrumAsync(conversationId); if (scrumInfo.IsScrumRunning) { var activityId = this.GetActivityIdToMatch(scrumInfo.MembersActivityIdMap, turnContext.Activity.From.Id); // check if member in scrum exists. // A user is added during a running scrum and tries to complete the running scrum. if (activityId == null) { await turnContext.SendActivityAsync(string.Format(Resources.NoPartOfCompleteScrumText, turnContext.Activity.From.Name)); this.telemetryClient.TrackTrace($"Member who is updating the scrum is not the part of scrum for : {conversationId}"); } else { var cardId = scrumInfo.ScrumStartActivityId; var activity = MessageFactory.Attachment(ScrumCompleteCard.GetScrumCompleteCard()); activity.Id = cardId; activity.Conversation = turnContext.Activity.Conversation; await turnContext.UpdateActivityAsync(activity, cancellationToken); // Update the trail card var dateString = string.Format("{{{{TIME({0})}}}}", DateTime.UtcNow.ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'Z'")); string cardTrailMessage = string.Format(Resources.ScrumCompletedByText, turnContext.Activity.From.Name, dateString); await this.UpdateTrailCard(cardTrailMessage, turnContext, cancellationToken); scrumInfo.IsScrumRunning = false; scrumInfo.ThreadConversationId = conversationId; var savedData = await this.scrumProvider.SaveOrUpdateScrumAsync(scrumInfo); if (!savedData) { await turnContext.SendActivityAsync(Resources.ErrorMessage); return; } this.telemetryClient.TrackTrace($"Scrum completed by: {turnContext.Activity.From.Name} for {conversationId}"); } } else { await turnContext.SendActivityAsync(Resources.CompleteScrumErrorText); } break; default: await turnContext.SendActivityAsync(MessageFactory.Attachment(HelpCard.GetHelpCard()), cancellationToken); break; } } } else { await turnContext.SendActivityAsync(Resources.ScopeErrorMessage); } } catch (Exception ex) { this.telemetryClient.TrackTrace($"For {turnContext.Activity.Conversation.Id} : Message Activity failed: {ex.Message}"); this.telemetryClient.TrackException(ex); } }
/// <summary> /// When OnTurn method receives a message activity on bot turn, it calls this method. /// </summary> /// <param name="turnContext">Provides context for a turn of a bot.</param> /// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param> /// <returns>A task that represents the work queued to execute.</returns> protected override async Task OnMessageActivityAsync(ITurnContext <IMessageActivity> turnContext, CancellationToken cancellationToken) { try { var activity = turnContext.Activity; // if card from messaging extension is sent to the bot conversation. if (activity.Attachments != null) { return; } else { var command = activity.Text; await this.SendTypingIndicatorAsync(turnContext).ConfigureAwait(false); if (activity.Text == null && activity.Value != null && activity.Type == ActivityTypes.Message) { command = JToken.Parse(activity.Value.ToString()).SelectToken("command").ToString(); } switch (command.ToUpperInvariant().Trim()) { case Constants.MyProfile: await this.dialog.RunAsync(turnContext, this.conversationState.CreateProperty <DialogState>(nameof(DialogState)), cancellationToken).ConfigureAwait(false); break; case Constants.Search: await this.dialog.RunAsync(turnContext, this.conversationState.CreateProperty <DialogState>(nameof(DialogState)), cancellationToken).ConfigureAwait(false); break; default: await turnContext.SendActivityAsync(MessageFactory.Attachment(HelpCard.GetHelpCard())).ConfigureAwait(false); break; } } } catch (Exception ex) { this.logger.LogError(ex, $"Error in message activity of bot for {turnContext.Activity.Conversation.Id}"); } }
/// <summary> /// Check for unknown input, and show the help prompt. /// </summary> /// <param name="stepContext">Provides context for a step in a bot dialog.</param> /// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param> /// <returns>Tracking task.</returns> private async Task <DialogTurnResult> CheckForUnknownInputAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken) { var activity = stepContext.Context.Activity; if (activity.Type == ActivityTypes.Message) { if (activity.Text == null) { return(await stepContext.NextAsync()); } else if (activity.Text.Trim().Equals(Strings.BotCommandMyProfile, StringComparison.CurrentCultureIgnoreCase) || activity.Text.Trim().Equals(Strings.BotCommandSearch, StringComparison.CurrentCultureIgnoreCase)) { return(await stepContext.NextAsync()); } else { await stepContext.Context.SendActivityAsync(MessageFactory.Attachment(HelpCard.GetHelpCard())).ConfigureAwait(false); return(await stepContext.EndDialogAsync().ConfigureAwait(false)); } } return(await stepContext.NextAsync()); }
/// <summary> /// Get user profile or search or edit profile based on activity type. /// </summary> /// <param name="stepContext">Provides context for a step in a bot dialog.</param> /// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param> /// <returns>Tracking task.</returns> private async Task <DialogTurnResult> MyProfileAndSearchAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken) { var activity = stepContext.Context.Activity; var tokenResponse = (TokenResponse)stepContext.Result; if (tokenResponse == null) { this.logger.LogInformation($"User is not authenticated and token is null for: {activity.Conversation.Id}."); await stepContext.Context.SendActivityAsync(Strings.NotLoggedInText).ConfigureAwait(false); return(await stepContext.EndDialogAsync().ConfigureAwait(false)); } var token = tokenResponse.Token; // signin/verifyState activity name used here to send my profile card after successful sign in. if ((activity.Type == MessageActivityType) || (activity.Name == SignInActivityName)) { var command = ((string)stepContext.Values["command"]).Trim(); if (command.Equals(Strings.BotCommandMyProfile, StringComparison.CurrentCultureIgnoreCase) || command.Equals(Constants.MyProfile)) { this.logger.LogInformation("My profile command triggered", new Dictionary <string, string>() { { "User", activity.From.Id }, { "AADObjectId", activity.From.AadObjectId } }); await this.MyProfileAsync(token, stepContext, cancellationToken).ConfigureAwait(false); } else if (command.Equals(Strings.BotCommandSearch, StringComparison.CurrentCultureIgnoreCase) || command.Equals(Constants.Search)) { this.logger.LogInformation("Search command triggered", new Dictionary <string, string>() { { "User", activity.From.Id }, { "AADObjectId", activity.From.AadObjectId } }); await stepContext.Context.SendActivityAsync(MessageFactory.Attachment(SearchCard.GetSearchCard())).ConfigureAwait(false); } else { await stepContext.Context.SendActivityAsync(MessageFactory.Attachment(HelpCard.GetHelpCard())).ConfigureAwait(false); } } // submit-invoke request at edit profile else if (activity.Type == InvokeActivityType) { await this.EditProfileAsync(token, stepContext, cancellationToken).ConfigureAwait(false); } return(await stepContext.EndDialogAsync().ConfigureAwait(false)); }
/// <summary> /// Check for unknown input, and show the help prompt. /// </summary> /// <param name="stepContext">Provides context for a step in a bot dialog.</param> /// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param> /// <returns>Tracking task.</returns> private async Task <DialogTurnResult> CheckForUnknownInputAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken) { var activity = stepContext.Context.Activity; if (activity.Type == ActivityTypes.Message) { switch (activity.Text?.Trim()) { case Constants.MyProfile: case Constants.Search: case null: return(await stepContext.NextAsync()); default: await stepContext.Context.SendActivityAsync(MessageFactory.Attachment(HelpCard.GetHelpCard())).ConfigureAwait(false); return(await stepContext.EndDialogAsync().ConfigureAwait(false)); } } return(await stepContext.NextAsync()); }
/// <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) { string actionType = message.Value != null?JObject.Parse(message.Value.ToString())["AdaptiveActionType"]?.ToString() : null; string scrumMembers = message.Value != null?JObject.Parse(message.Value.ToString())["ScrumMembers"]?.ToString() : null; message.RemoveRecipientMention(); string text = string.IsNullOrEmpty(message.Text) ? actionType : message.Text; switch (text.ToUpperInvariant().Trim()) { case Constants.EndScrum: // command to handle end scrum. string conversationId = message.Conversation.Id; string scrumTeamConfigId = JObject.Parse(message.Value.ToString())["ScrumTeamConfigId"].ToString(); string aadGroupId = await this.activityHelper.GetTeamAadGroupIdAsync(turnContext, cancellationToken); var scrumInfo = await this.scrumHelper.GetActiveScrumAsync(scrumTeamConfigId, aadGroupId); if (scrumInfo == null || scrumInfo.IsCompleted) { await turnContext.SendActivityAsync(string.Format(CultureInfo.CurrentCulture, this.localizer.GetString("ErrorScrumDoesNotExist"), turnContext.Activity.From.Name), cancellationToken : cancellationToken); break; } scrumInfo.IsCompleted = true; scrumInfo.ThreadConversationId = conversationId; var scrumSaveResponse = await this.scrumStorageProvider.CreateOrUpdateScrumAsync(scrumInfo); if (!scrumSaveResponse) { this.logger.LogError("Error in saving scrum information in storage."); await turnContext.SendActivityAsync(this.localizer.GetString("ErrorSavingScrumData"), cancellationToken : cancellationToken); break; } var activitySummary = await this.activityHelper.GetEndScrumSummaryActivityAsync(scrumInfo, conversationId, scrumMembers, turnContext, cancellationToken); if (activitySummary != null) { this.logger.LogInformation($"Scrum completed by: {turnContext.Activity.From.AadObjectId} for {conversationId} with ScrumStartCardResponseId: {scrumInfo.ScrumStartCardResponseId}"); await turnContext.UpdateActivityAsync(activitySummary, cancellationToken); await turnContext.SendActivityAsync(this.localizer.GetString("SuccessMessageAfterEndingScrum"), cancellationToken : cancellationToken); } break; case Constants.Help: // command to show help card. this.logger.LogInformation("Sending help card"); var helpAttachment = HelpCard.GetHelpCard(this.localizer); await turnContext.SendActivityAsync(MessageFactory.Attachment(helpAttachment), cancellationToken); break; case Constants.Settings: // Command to show adaptive card with settings CTA button. this.logger.LogInformation("Sending settings button card"); var settingsAttachment = SettingsCard.GetSettingsCard(this.localizer); await turnContext.SendActivityAsync(MessageFactory.Attachment(settingsAttachment), cancellationToken); break; default: this.logger.LogInformation("Invalid command text entered in channel. Sending help card"); var helpAttachmentcard = HelpCard.GetHelpCard(this.localizer); await turnContext.SendActivityAsync(MessageFactory.Attachment(helpAttachmentcard), cancellationToken); break; } }