Esempio n. 1
0
        // Create a new ticket from the input
        private async Task <TicketEntity> CreateTicketAsync(IMessageActivity message, AskAnExpertCardPayload data, TeamsChannelAccount member)
        {
            TicketEntity ticketEntity = new TicketEntity
            {
                TicketId      = Guid.NewGuid().ToString(),
                Status        = (int)TicketState.Open,
                DateCreated   = DateTime.UtcNow,
                Title         = data.Title,
                Description   = data.Description,
                RequesterName = member.Name,
                RequesterUserPrincipalName = member.UserPrincipalName,
                RequesterGivenName         = member.GivenName,
                RequesterConversationId    = message.Conversation.Id,
                LastModifiedByName         = message.From.Name,
                LastModifiedByObjectId     = message.From.AadObjectId,
                UserQuestion        = data.UserQuestion,
                KnowledgeBaseAnswer = data.KnowledgeBaseAnswer
            };

            await this.ticketsProvider.SaveOrUpdateTicketAsync(ticketEntity);

            return(ticketEntity);
        }
Esempio n. 2
0
        /// <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,
                            };

                            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;
            }
        }
Esempio n. 3
0
        private static async Task <Attachment> GetDetailedRoasterCard(Activity activity, TeamsChannelAccount userDetails)
        {
            var  details = JsonConvert.DeserializeObject <AirlineActionDetails>(activity.Value.ToString());
            Crew crew    = await CabinCrewPlansHelper.ReadJson(userDetails.UserPrincipalName);

            var datePlan = crew.plan.FirstOrDefault(c => c.flightDetails.flightStartDate.Date.ToString() == details.Id);

            return(CardHelper.GetDetailedRoster(datePlan));
        }
        /// <summary>
        /// This method will construct the card for SME team which will have the
        /// feedback details given by the user.
        /// </summary>
        /// <param name="data">user activity payload</param>
        /// <param name="userDetails">User details.</param>
        /// <returns>Sme facing feedback notification card.</returns>
        public static Attachment GetCard(ShareFeedbackCardPayload data, TeamsChannelAccount userDetails)
        {
            // Constructing adaptive card that is sent to SME team.
            AdaptiveCard smeFeedbackCard = new AdaptiveCard("1.0")
            {
                Body = new List <AdaptiveElement>
                {
                    new AdaptiveTextBlock()
                    {
                        Text   = Resource.SMEFeedbackHeaderText,
                        Weight = AdaptiveTextWeight.Bolder,
                        Size   = AdaptiveTextSize.Medium,
                    },
                    new AdaptiveTextBlock()
                    {
                        Text = string.Format(Resource.FeedbackAlertText, userDetails.Name),
                        Wrap = true,
                    },
                    new AdaptiveTextBlock()
                    {
                        Text   = Resource.RatingTitle,
                        Weight = AdaptiveTextWeight.Bolder,
                        Wrap   = true,
                    },
                    new AdaptiveTextBlock()
                    {
                        Text    = GetRatingDisplayText(data.Rating),
                        Spacing = AdaptiveSpacing.None,
                        Wrap    = true,
                    },
                },
                Actions = new List <AdaptiveAction>
                {
                    new AdaptiveOpenUrlAction
                    {
                        Title     = string.Format(Resource.ChatTextButton, userDetails.GivenName),
                        UrlString = $"https://teams.microsoft.com/l/chat/0/0?users={Uri.EscapeDataString(userDetails.UserPrincipalName)}"
                    }
                }
            };

            // Description fact is available in the card only when user enters description text.
            if (!string.IsNullOrWhiteSpace(data.Description))
            {
                smeFeedbackCard.Body.Add(new AdaptiveTextBlock()
                {
                    Text   = Resource.DescriptionText,
                    Weight = AdaptiveTextWeight.Bolder,
                    Wrap   = true,
                });
                smeFeedbackCard.Body.Add(new AdaptiveTextBlock()
                {
                    Text    = CardHelper.TruncateStringIfLonger(data.Description, CardHelper.DescriptionMaxDisplayLength),
                    Spacing = AdaptiveSpacing.None,
                    Wrap    = true,
                });
            }

            // Question asked fact and view article show card is available when feedback is on QnA Maker response.
            if (!string.IsNullOrWhiteSpace(data.KnowledgeBaseAnswer) && !string.IsNullOrWhiteSpace(data.UserQuestion))
            {
                smeFeedbackCard.Body.Add(new AdaptiveFactSet
                {
                    Facts = new List <AdaptiveFact>
                    {
                        new AdaptiveFact()
                        {
                            Title = Resource.QuestionAskedFactTitle,
                            Value = data.UserQuestion,
                        },
                    }
                });
                smeFeedbackCard.Actions.AddRange(new List <AdaptiveAction>
                {
                    new AdaptiveShowCardAction
                    {
                        Title = Resource.ViewArticleButtonText,
                        Card  = new AdaptiveCard("1.0")
                        {
                            Body = new List <AdaptiveElement>
                            {
                                new AdaptiveTextBlock
                                {
                                    Text = CardHelper.TruncateStringIfLonger(data.KnowledgeBaseAnswer, CardHelper.KnowledgeBaseAnswerMaxDisplayLength),
                                    Wrap = true
                                }
                            }
                        }
                    }
                });
            }

            return(new Attachment
            {
                ContentType = AdaptiveCard.ContentType,
                Content = smeFeedbackCard,
            });
        }
        /// <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);
            }
        }
Esempio n. 6
0
        /// <summary>
        /// Create a new ticket from the input.
        /// </summary>
        /// <param name="turnContext">Context object containing information cached for a single turn of conversation with a user.</param>
        /// <param name="ticketDetail">Ticket details from requested user.</param>
        /// <param name="ticketAdditionalDetails">Additional ticket details.</param>
        /// <param name="cardId">Card template id.</param>
        /// <param name="member"> User details who is currently having conversation.</param>
        /// <returns>TicketDetail object.</returns>
        public static TicketDetail GetNewTicketDetails(ITurnContext <IMessageActivity> turnContext, TicketDetail ticketDetail, string ticketAdditionalDetails, string cardId, TeamsChannelAccount member)
        {
            turnContext  = turnContext ?? throw new ArgumentNullException(nameof(turnContext));
            ticketDetail = ticketDetail ?? throw new ArgumentNullException(nameof(ticketDetail));

            ticketDetail.CreatedOn = ConvertToDateTimeoffset(DateTime.Now, turnContext.Activity.LocalTimestamp.Value.Offset);
            if (ticketDetail.IssueOccuredOn == DateTimeOffset.MinValue)
            {
                ticketDetail.IssueOccuredOn = ConvertToDateTimeoffset(DateTime.Now, turnContext.Activity.LocalTimestamp.Value.Offset);
            }
            else
            {
                ticketDetail.IssueOccuredOn = ConvertToDateTimeoffset(ticketDetail.IssueOccuredOn, turnContext.Activity.LocalTimestamp.Value.Offset);
            }

            ticketDetail.CreatedByObjectId          = turnContext.Activity.From.AadObjectId;
            ticketDetail.CreatedByUserPrincipalName = member?.UserPrincipalName;
            ticketDetail.RequesterName             = member.Name;
            ticketDetail.RequesterConversationId   = turnContext.Activity.Conversation.Id;
            ticketDetail.RequesterTicketActivityId = turnContext.Activity.ReplyToId;
            ticketDetail.SmeConversationId         = null;
            ticketDetail.SmeTicketActivityId       = null;
            ticketDetail.TicketStatus         = (int)TicketState.Unassigned;
            ticketDetail.Severity             = (int)(TicketSeverity)Enum.Parse(typeof(TicketSeverity), ticketDetail.RequestType ?? TicketSeverity.Normal.ToString());
            ticketDetail.AdditionalProperties = CardHelper.ValidateAdditionalTicketDetails(ticketAdditionalDetails, turnContext.Activity.LocalTimestamp.Value.Offset);
            ticketDetail.CardId             = cardId;
            ticketDetail.AssignedToName     = string.Empty;
            ticketDetail.AssignedToObjectId = string.Empty;

            return(ticketDetail);
        }
        private static async Task <Attachment> GetDetailedRoasterCard(Activity activity, TeamsChannelAccount userDetails, GraphHelper graphHelper, IConfiguration configuration)
        {
            var details = JsonConvert.DeserializeObject <AirlineActionDetails>(activity.Value.ToString());
            // Crew crew = await CabinCrewPlansHelper.ReadJson(userDetails.UserPrincipalName);

            string crewid = await graphHelper.GetUserEmployeeIdAsync(userDetails.UserPrincipalName);

            Crew crew = await CabinCrewPlansHelper.ReadJson(crewid, configuration);

            // Crew crew = await CabinCrewPlansHelper.ReadJson("10055"); // ${Debugging}
            var datePlan = crew.plan.FirstOrDefault(c => c.flightDetails.flightStartDate.Date.ToString() == details.Id);

            return(CardHelper.GetDetailedRoster(datePlan));
        }
        private async Task HandleActions(ITurnContext context, CancellationToken cancellationToken, Activity activity, TeamsChannelAccount userDetails)
        {
            var actionDetails = JsonConvert.DeserializeObject <ActionDetails>(activity.Value.ToString());
            // var userDetails = await TeamsInfo.GetMemberAsync(context, context.Activity.From.Id);//await GetCurrentUserDetails(activity);
            var type = actionDetails.ActionType;

            Attachment card   = null;
            string     crewid = string.Empty;

            switch (type)
            {
            case Constants.ShowDetailedRoster:
                card = await GetDetailedRoasterCard(activity, userDetails, this.graphHelper, configuration);

                break;

            case Constants.NextWeekRoster:
                crewid = await graphHelper.GetUserEmployeeIdAsync(userDetails.UserPrincipalName);

                card = await CardHelper.GetWeeklyRosterCard(crewid, configuration);

                // card = await CardHelper.GetWeeklyRosterCard("10055"); // ${Debugging}
                break;

            case Constants.NextMonthRoster:
                crewid = await graphHelper.GetUserEmployeeIdAsync(userDetails.UserPrincipalName);

                card = CardHelper.GetMonthlyRosterCard(crewid);
                break;

            case Constants.WeatherCard:
                card = await GetWeatherCard(activity);

                break;

            case Constants.CurrencyCard:
                card = await GetCurrencyCard(activity);

                break;
            }

            await context.SendActivityAsync(MessageFactory.Attachment(card), cancellationToken);
        }
Esempio n. 9
0
 /// <summary>
 /// Checks whether or not the account is a guest user.
 /// </summary>
 /// <param name="account">The <see cref="TeamsChannelAccount"/> user to check.</param>
 /// <returns>True if the account is a guest user, false otherwise.</returns>
 private static bool IsGuestUser(TeamsChannelAccount account)
 {
     return(account.UserPrincipalName.IndexOf(ExternallyAuthenticatedUpnMarker, StringComparison.InvariantCultureIgnoreCase) >= 0);
 }
Esempio n. 10
0
        /// <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(this.localizer.GetString("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);
        }
Esempio n. 11
0
        /// <summary>
        /// Method creates a private channel based on grouping result obtained from grouping criteria.
        /// </summary>
        /// <param name="accessToken">Token to access Microsoft Graph API.</param>
        /// <param name="groupId">Team Azure Active Directory object id of the channel where bot is installed.</param>
        /// <param name="membersGroupingWithChannel">A dictionary with members grouped into channels based on entered grouping criteria.</param>
        /// <param name="groupActivityCreator">Team owner who initiated group activity.</param>
        /// <param name="groupDetail">Values entered by user in task module.</param>
        /// <returns>Return the List of channels created using Microsoft Graph API.</returns>
        private async Task <Tuple <List <ChannelApiResponse>, List <string> > > CreatePrivateChannelAsync(string accessToken, string groupId, Dictionary <int, IList <TeamsChannelAccount> > membersGroupingWithChannel, TeamsChannelAccount groupActivityCreator, GroupDetail groupDetail)
        {
            List <ChannelApiResponse> privateChannelApiResponses = new List <ChannelApiResponse>();
            var notCreatedChannels = new List <string>();

            try
            {
                var privateChannelRequestData = new PrivateChannelRequest();
                var channelCount = 1;
                foreach (var groupedChannel in membersGroupingWithChannel)
                {
                    privateChannelRequestData.DisplayName    = $"{groupDetail.GroupTitle}-{channelCount}";
                    privateChannelRequestData.Description    = groupDetail.GroupDescription;
                    privateChannelRequestData.MembershipType = groupDetail.ChannelType;
                    privateChannelRequestData.Members        = new List <ChannelMember>();

                    foreach (var groupMember in groupedChannel.Value)
                    {
                        var role = groupActivityCreator.AadObjectId.Contains(groupMember.AadObjectId) ? OwnerUserRole : MemberUserRole;
                        privateChannelRequestData.Members.Add(new ChannelMember {
                            UserOdataBind = $"{ChannelMemberGraphUrl}('{groupMember.AadObjectId}')", Roles = new List <string> {
                                role
                            }
                        });
                    }

                    string createChannelData = JsonConvert.SerializeObject(privateChannelRequestData);

                    var privateChannels = await this.graphApiHelper.CreatePrivateChannelAsync(accessToken, createChannelData, groupId);

                    if (privateChannels != null)
                    {
                        privateChannelApiResponses.Add(privateChannels);
                    }
                    else
                    {
                        notCreatedChannels.Add(string.Format("*{0}*", privateChannels.DisplayName));
                        this.logger.LogInformation($"Not able to create channel for: {privateChannels.DisplayName}");
                    }

                    channelCount++;
                }

                return(new Tuple <List <ChannelApiResponse>, List <string> >(privateChannelApiResponses, notCreatedChannels));
            }
            catch (Exception ex)
            {
                this.logger.LogError(ex, "Error while creating private channel for the team.");
                return(null);
            }
        }
Esempio n. 12
0
        /// <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}");
            }
        }
Esempio n. 13
0
        /// <summary>
        /// Validate channel count and create channel using Microsoft Graph API.
        /// </summary>
        /// <param name="token">Token to access Microsoft Graph API.</param>
        /// <param name="groupActivityId">Guid 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="groupingMessage">Grouping message with members mapped to groups.</param>
        /// <param name="valuesFromTaskModule">Group activity details obtained from task module as 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>
        public async Task ValidateAndCreateChannelAsync(string token, string groupActivityId, string teamId, string groupId, string groupingMessage, GroupDetail valuesFromTaskModule, Dictionary <int, IList <TeamsChannelAccount> > membersGroupingWithChannel, TeamsChannelAccount groupActivityCreator, ITurnContext <IInvokeActivity> turnContext, CancellationToken cancellationToken)
        {
            // Validate that channel count to be created are in limit with public channels less than 200 and private channel 30.
            bool?isValidChannelCount = await this.ValidateChannelCountAsync(token, valuesFromTaskModule.ChannelType, membersGroupingWithChannel.Count, groupId);

            if (isValidChannelCount == null)
            {
                await turnContext.SendActivityAsync(Strings.CustomErrorMessage);

                this.logger.LogInformation($"Channel count is null for teamId : {teamId}");
                return;
            }

            if (isValidChannelCount == false)
            {
                await turnContext.SendActivityAsync(Strings.ChannelCountValidationText);

                this.logger.LogInformation($"Channel count is not valid for teamId : {teamId}");
                return;
            }

            this.taskWrapper.Enqueue(this.CreateChannelAsync(token, groupActivityId, teamId, groupId, valuesFromTaskModule, membersGroupingWithChannel, groupActivityCreator, groupingMessage, turnContext, cancellationToken));
        }