/// <summary> /// Create public or private channel based on grouping criteria. /// </summary> /// <param name="accessToken">Token to access Microsoft Graph API.</param> /// <param name="groupActivityId">group activity Id.</param> /// <param name="teamId">Team id where messaging extension is installed.</param> /// <param name="groupId">Team Azure Active Directory object id of the channel where bot is installed.</param> /// <param name="valuesFromTaskModule">Group activity details from task module entered by user.</param> /// <param name="membersGroupingWithChannel">List of all members grouped in channels based on grouping criteria.</param> /// <param name="groupActivityCreator">Team owner who started the group activity.</param> /// <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 returns true if channel is created successfully.</returns> private async Task CreateChannelAsync(string accessToken, string groupActivityId, string teamId, string groupId, GroupDetail valuesFromTaskModule, Dictionary <int, IList <TeamsChannelAccount> > membersGroupingWithChannel, TeamsChannelAccount groupActivityCreator, string groupingMessage, ITurnContext <IInvokeActivity> turnContext, CancellationToken cancellationToken) { try { string channelType = valuesFromTaskModule.ChannelType; Tuple <List <ChannelApiResponse>, List <string> > channelDetails = null; switch (channelType) { case Constants.PublicChannelType: channelDetails = await this.CreatePublicChannelAsync(accessToken, membersGroupingWithChannel, valuesFromTaskModule, groupId, groupActivityCreator.Name, groupingMessage, turnContext, cancellationToken); break; case Constants.PrivateChannelType: channelDetails = await this.CreatePrivateChannelAsync(accessToken, groupId, membersGroupingWithChannel, groupActivityCreator, valuesFromTaskModule); break; } if (channelDetails != null && channelDetails.Item1.Count > 0) { bool isChannelInfoSaved = await this.StoreChannelsCreatedDetailsAsync(teamId, groupActivityId, channelType, channelDetails.Item1, turnContext); if (!isChannelInfoSaved) { await turnContext.SendActivityAsync(Strings.CustomErrorMessage); this.logger.LogInformation($"Saving newly created channel details to table storage failed for teamId: {teamId}."); } } // show the list of channels to the user which are failed to get created. if (channelDetails.Item2.Count > 0) { StringBuilder channelsNotCreated = new StringBuilder(); foreach (var channel in channelDetails.Item2) { channelsNotCreated.AppendLine(channel).AppendLine(); } this.logger.LogError($"Number of channels failed to get created. TotalChannels {channelDetails.Item2.Count.ToString()}, Team {teamId}"); await turnContext.SendActivityAsync(MessageFactory.Attachment(GroupActivityCard.GetChannelCreationFailedCard(channelsNotCreated.ToString(), valuesFromTaskModule.GroupTitle))); } } catch (Exception ex) { await turnContext.SendActivityAsync(Strings.CustomErrorMessage); this.logger.LogError(ex, $"Error while creating channels for teamId: {teamId}"); } }
/// <summary> /// Show validation card if inputs in task module are not valid. /// </summary> /// <param name="groupDetail">groupDetail is the values obtained from task module.</param> /// <param name="isSplittingValid">split condition valid flag.</param> /// <returns>A task that sends validation card in task module.</returns> private MessagingExtensionActionResponse ShowValidationForCreateChannel(GroupDetail groupDetail, bool isSplittingValid) { return(new MessagingExtensionActionResponse { Task = new TaskModuleContinueResponse { Value = new TaskModuleTaskInfo { Card = GroupActivityCard.GetGroupActivityValidationCard(groupDetail, isSplittingValid), Height = TaskModuleHeight, Width = TaskModuleWidth, }, }, }); }
/// <summary> /// Send Grouping message in channel from where group activity is invoked. /// </summary> /// <param name="teamId">Team id of team where bot is installed.</param> /// <param name="valuesFromTaskModule">Values obtained from task modules which entered by user.</param> /// <param name="membersGroupingWithChannel">A dictionary with members grouped into channels based on entered grouping criteria.</param> /// <param name="groupActivityCreator">Team owner who initiated the group activity.</param> /// <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 sends the grouping message in channel.</returns> private async Task <string> SendAndStoreGroupingMessageAsync(string groupActivityId, string teamId, GroupDetail valuesFromTaskModule, Dictionary <int, IList <TeamsChannelAccount> > membersGroupingWithChannel, TeamsChannelAccount groupActivityCreator, ITurnContext <IInvokeActivity> turnContext, CancellationToken cancellationToken) { try { // Post grouping of members with channel details to channel from where bot is invoked. var groupingMessage = this.groupingHelper.GroupingMessage(valuesFromTaskModule, membersGroupingWithChannel, groupActivityCreator.Name); var groupingCardActivity = MessageFactory.Attachment(GroupActivityCard.GetGroupActivityCard(groupingMessage, groupActivityCreator.Name, valuesFromTaskModule)); await turnContext.SendActivityAsync(groupingCardActivity, cancellationToken); await this.channelHelper.StoreGroupActivityDetailsAsync(turnContext.Activity.ServiceUrl, groupActivityId, teamId, valuesFromTaskModule, groupActivityCreator.Name, groupingCardActivity.Conversation.Id, groupingCardActivity.Id); return(groupingMessage); } catch (Exception ex) { this.logger.LogError(ex, $"Error while creating grouping message for group activity for teamId - {teamId}"); return(null); } }
/// <summary> /// Handle message extension action fetch task received by the bot. /// </summary> /// <param name="turnContext">Provides context for a turn of a bot.</param> /// <param name="action">Messaging extension action value payload.</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 returns messagingExtensionActionResponse.</returns> protected override async Task <MessagingExtensionActionResponse> OnTeamsMessagingExtensionFetchTaskAsync(ITurnContext <IInvokeActivity> turnContext, MessagingExtensionAction action, CancellationToken cancellationToken) { var activity = turnContext.Activity; var activityState = ((JObject)activity.Value).GetValue("state")?.ToString(); var tokenResponse = await(turnContext.Adapter as IUserTokenProvider).GetUserTokenAsync(turnContext, this.connectionName, activityState, cancellationToken); if (tokenResponse == null) { var signInLink = await(turnContext.Adapter as IUserTokenProvider).GetOauthSignInLinkAsync(turnContext, this.connectionName, cancellationToken); return(new MessagingExtensionActionResponse { ComposeExtension = new MessagingExtensionResult { Type = MessagingExtensionAuthType, SuggestedActions = new MessagingExtensionSuggestedAction { Actions = new List <CardAction> { new CardAction { Type = ActionTypes.OpenUrl, Value = signInLink, Title = Strings.SigninCardText, }, }, }, }, }); } var teamInformation = activity.TeamsGetTeamInfo(); if (teamInformation == null || string.IsNullOrEmpty(teamInformation.Id)) { return(new MessagingExtensionActionResponse { Task = new TaskModuleContinueResponse { Value = new TaskModuleTaskInfo { Card = GroupActivityCard.GetTeamNotFoundErrorCard(), Height = TaskModuleValidationHeight, Width = TaskModuleValidationWidth, Title = Strings.GroupActivityTitle, }, }, }); } TeamDetails teamDetails; try { teamDetails = await TeamsInfo.GetTeamDetailsAsync(turnContext, teamInformation.Id, cancellationToken); } catch (Exception ex) { // if bot is not installed in team or not able to team roster, then show error response. this.logger.LogError("Bot is not part of team roster", ex); return(new MessagingExtensionActionResponse { Task = new TaskModuleContinueResponse { Value = new TaskModuleTaskInfo() { Card = GroupActivityCard.GetTeamNotFoundErrorCard(), Height = TaskModuleHeight, Width = TaskModuleHeight, }, }, }); } if (teamDetails == null) { this.logger.LogInformation($"Team details obtained is null."); return(new MessagingExtensionActionResponse { Task = new TaskModuleContinueResponse { Value = new TaskModuleTaskInfo { Card = GroupActivityCard.GetErrorMessageCard(), Height = TaskModuleValidationHeight, Width = TaskModuleValidationWidth, Title = Strings.GroupActivityTitle, }, }, }); } var isTeamOwner = await this.teamUserHelper.VerifyIfUserIsTeamOwnerAsync(tokenResponse.Token, teamDetails.AadGroupId, activity.From.AadObjectId); if (isTeamOwner == null) { await turnContext.SendActivityAsync(Strings.CustomErrorMessage); return(new MessagingExtensionActionResponse { Task = new TaskModuleContinueResponse { Value = new TaskModuleTaskInfo { Card = GroupActivityCard.GetErrorMessageCard(), Height = TaskModuleValidationHeight, Width = TaskModuleValidationWidth, Title = Strings.GroupActivityTitle, }, }, }); } // If user is team member validation message is shown as only team owner can create a group activity. if (isTeamOwner == false) { return(new MessagingExtensionActionResponse { Task = new TaskModuleContinueResponse { Value = new TaskModuleTaskInfo { Card = GroupActivityCard.GetTeamOwnerErrorCard(), Height = TaskModuleValidationHeight, Width = TaskModuleValidationWidth, Title = Strings.GroupActivityTitle, }, }, }); } // Team owner can create group activity. return(new MessagingExtensionActionResponse { Task = new TaskModuleContinueResponse { Value = new TaskModuleTaskInfo { Card = GroupActivityCard.GetCreateGroupActivityCard(), Height = TaskModuleHeight, Width = TaskModuleWidth, Title = Strings.GroupActivityTitle, }, }, }); }