/// <summary> /// Get team posts as per configured categories for preference. /// </summary> /// <param name="teamPreferenceEntity">Team preference model object.</param> /// <param name="teamPosts">List of team posts.</param> /// <returns>List of team posts as per preference categories.</returns> private IEnumerable <IdeaEntity> GetDataAsPerCategories( TeamPreferenceEntity teamPreferenceEntity, IEnumerable <IdeaEntity> teamPosts) { var filteredPosts = new List <IdeaEntity>(); var preferenceCategoryIdsList = teamPreferenceEntity.Categories.Split(";").Where(category => !string.IsNullOrWhiteSpace(category)).ToList(); teamPosts = teamPosts.OrderByDescending(c => c.UpdatedDate); // Loop through the list of filtered posts. foreach (var teamPost in teamPosts) { // Loop through the list of preference category ids. foreach (var preferenceCategoryId in preferenceCategoryIdsList) { if (teamPost.CategoryId == preferenceCategoryId && filteredPosts.Count < MaxIdeasForNotification) { // If preference category is present then add it in the list. filteredPosts.Add(teamPost); break; // break the inner loop to check for next post. } } // Break the entire loop after getting top 15 posts. if (filteredPosts.Count >= MaxIdeasForNotification) { break; } } return(filteredPosts); }
/// <summary> /// Stores or update team preference data in storage. /// </summary> /// <param name="teamPreferenceEntity">Holds team preference detail entity data.</param> /// <returns>A task that represents team preference entity data is saved or updated.</returns> private async Task <TableResult> StoreOrUpdateTeamPreferenceAsync(TeamPreferenceEntity teamPreferenceEntity) { await this.EnsureInitializedAsync(); TableOperation addOrUpdateOperation = TableOperation.InsertOrReplace(teamPreferenceEntity); return(await this.GoodReadsCloudTable.ExecuteAsync(addOrUpdateOperation)); }
/// <summary> /// Get team posts as per configured tags for preference. /// </summary> /// <param name="teamPreferenceEntity">Team preference model object.</param> /// <param name="teamPosts">List of team posts.</param> /// <returns>List of team posts as per preference tags.</returns> private IEnumerable <PostEntity> GetDataAsPerTags( TeamPreferenceEntity teamPreferenceEntity, IEnumerable <PostEntity> teamPosts) { var filteredPosts = new List <PostEntity>(); var preferenceTagList = teamPreferenceEntity.Tags.Split(";").Where(tag => !string.IsNullOrWhiteSpace(tag)); bool isTagMatched = false; teamPosts = teamPosts.OrderByDescending(c => c.UpdatedDate); // Loop through the list of filtered posts. foreach (var teamPost in teamPosts) { // Split the comma separated post tags. var postTags = teamPost.Tags.Split(";").Where(tag => !string.IsNullOrWhiteSpace(tag)); isTagMatched = false; // Loop through the list of preference tags. foreach (var preferenceTag in preferenceTagList) { // Loop through the post tags. foreach (var postTag in postTags) { // Check if the post tag and preference tag is same. if (postTag.Trim() == preferenceTag.Trim()) { // Set the flag to check the preference tag is present in post tag. isTagMatched = true; break; // break the loop to check for next preference tag with post tag. } } if (isTagMatched && filteredPosts.Count < ListCardPostCount) { // If preference tag is present in post tag then add it in the list. filteredPosts.Add(teamPost); break; // break the inner loop to check for next post. } } // Break the entire loop after getting top {ListCardPostCount} posts. if (filteredPosts.Count >= ListCardPostCount) { break; } } return(filteredPosts.Take(ListCardPostCount)); }
/// <summary> /// Stores or update team preference data in Microsoft Azure Table storage. /// </summary> /// <param name="teamPreferenceEntity">Holds team preference detail entity data.</param> /// <returns>A task that represents team preference entity data is saved or updated.</returns> private async Task <TableResult> StoreOrUpdateEntityAsync(TeamPreferenceEntity teamPreferenceEntity) { await this.EnsureInitializedAsync(); teamPreferenceEntity = teamPreferenceEntity ?? throw new ArgumentNullException(nameof(teamPreferenceEntity)); if (string.IsNullOrWhiteSpace(teamPreferenceEntity.DigestFrequency) || string.IsNullOrWhiteSpace(teamPreferenceEntity.Categories)) { return(null); } TableOperation addOrUpdateOperation = TableOperation.InsertOrReplace(teamPreferenceEntity); return(await this.CloudTable.ExecuteAsync(addOrUpdateOperation)); }
/// <summary> /// Create team preference model data. /// </summary> /// <param name="entity">Represents team preference entity object.</param> /// <returns>Represents team preference entity model.</returns> public TeamPreferenceEntity CreateTeamPreferenceModel(TeamPreferenceEntity entity) { try { entity = entity ?? throw new ArgumentNullException(nameof(entity)); entity.TeamId = entity.TeamId; entity.CreatedDate = DateTime.UtcNow; entity.UpdatedDate = DateTime.UtcNow; return(entity); } catch (Exception ex) { this.logger.LogError(ex, "Exception occurred while preparing the team preference entity model data"); throw; } }
/// <summary> /// Send the given attachment to the specified team. /// </summary> /// <param name="teamPreferenceEntity">Team preference model object.</param> /// <param name="cardToSend">The attachment card to send.</param> /// <param name="serviceUrl">Service URL for a particular team.</param> /// <returns>A task that sends notification card in channel.</returns> private async Task SendCardToTeamAsync( TeamPreferenceEntity teamPreferenceEntity, Attachment cardToSend, string serviceUrl) { MicrosoftAppCredentials.TrustServiceUrl(serviceUrl); string teamsChannelId = teamPreferenceEntity.TeamId; var conversationReference = new ConversationReference() { ChannelId = Constants.TeamsBotFrameworkChannelId, Bot = new ChannelAccount() { Id = $"28:{this.botOptions.Value.MicrosoftAppId}" }, ServiceUrl = serviceUrl, Conversation = new ConversationAccount() { Id = teamsChannelId }, }; this.logger.LogInformation($"sending notification to channelId- {teamsChannelId}"); // Retry it in addition to the original call. await this.retryPolicy.ExecuteAsync(async() => { try { await((BotFrameworkAdapter)this.adapter).ContinueConversationAsync( this.botOptions.Value.MicrosoftAppId, conversationReference, async(conversationTurnContext, conversationCancellationToken) => { await conversationTurnContext.SendActivityAsync(MessageFactory.Attachment(cardToSend)); }, CancellationToken.None); } catch (Exception ex) { this.logger.LogError(ex, $"Error while performing retry logic to send digest notification to channel for team: {teamsChannelId}."); throw; } }); }
/// <summary> /// Stores or update team preference data in Microsoft Azure Table storage. /// </summary> /// <param name="teamPreferenceEntity">Represents team preference entity object.</param> /// <returns>A boolean that represents team preference entity is successfully saved/updated or not.</returns> public async Task <bool> UpsertTeamPreferenceAsync(TeamPreferenceEntity teamPreferenceEntity) { var result = await this.StoreOrUpdateEntityAsync(teamPreferenceEntity); return(result.HttpStatusCode == (int)HttpStatusCode.NoContent); }
/// <summary> /// When OnTurn method receives a submit invoke activity on bot turn, it calls this method. /// </summary> /// <param name="turnContext">Provides context for a turn of a bot.</param> /// <param name="taskModuleRequest">Task module invoke request 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 represents a task module response.</returns> protected override async Task <TaskModuleResponse> OnTeamsTaskModuleSubmitAsync(ITurnContext <IInvokeActivity> turnContext, TaskModuleRequest taskModuleRequest, CancellationToken cancellationToken) { try { if (turnContext == null || taskModuleRequest == null) { return(new TaskModuleResponse { Task = new TaskModuleContinueResponse { Type = "continue", Value = new TaskModuleTaskInfo() { Url = $"{this.options.Value.AppBaseUri}/error", Height = TaskModuleHeight, Width = TaskModuleWidth, Title = this.localizer.GetString("ApplicationName"), }, }, }); } var preferenceData = JsonConvert.DeserializeObject <Preference>(taskModuleRequest.Data?.ToString()); if (preferenceData == null) { this.logger.LogInformation($"Request data obtained on task module submit action is null."); await turnContext.SendActivityAsync(Strings.ErrorMessage).ConfigureAwait(false); return(null); } // If user clicks Cancel button in task module. if (preferenceData.Command == CloseCommand) { return(null); } if (preferenceData.Command == SubmitCommand) { // Save or update digest preference for team. if (preferenceData.ConfigureDetails != null) { var currentTeamPreferenceDetail = await this.teamPreferenceStorageProvider.GetTeamPreferenceAsync(preferenceData.ConfigureDetails.TeamId); TeamPreferenceEntity teamPreferenceDetail; if (currentTeamPreferenceDetail == null) { teamPreferenceDetail = new TeamPreferenceEntity { CreatedDate = DateTime.UtcNow, DigestFrequency = preferenceData.ConfigureDetails.DigestFrequency, Tags = preferenceData.ConfigureDetails.Tags, TeamId = preferenceData.ConfigureDetails.TeamId, UpdatedByName = turnContext.Activity.From.Name, UpdatedByObjectId = turnContext.Activity.From.AadObjectId, UpdatedDate = DateTime.UtcNow, RowKey = preferenceData.ConfigureDetails.TeamId, }; } else { currentTeamPreferenceDetail.DigestFrequency = preferenceData.ConfigureDetails.DigestFrequency; currentTeamPreferenceDetail.Tags = preferenceData.ConfigureDetails.Tags; teamPreferenceDetail = currentTeamPreferenceDetail; } var upsertResult = await this.teamPreferenceStorageProvider.UpsertTeamPreferenceAsync(teamPreferenceDetail); } else { this.logger.LogInformation("Preference details received from task module is null."); return(new TaskModuleResponse { Task = new TaskModuleContinueResponse { Type = "continue", Value = new TaskModuleTaskInfo() { Url = $"{this.options.Value.AppBaseUri}/error", Height = TaskModuleHeight, Width = TaskModuleWidth, Title = this.localizer.GetString("ApplicationName"), }, }, }); } } return(null); } #pragma warning disable CA1031 // Catching general exception for any errors occurred during saving data to table storage. catch (Exception ex) #pragma warning restore CA1031 // Catching general exception for any errors occurred during saving data to table storage. { this.logger.LogError(ex, "Error in submit action of task module."); return(new TaskModuleResponse { Task = new TaskModuleContinueResponse { Type = "continue", Value = new TaskModuleTaskInfo() { Url = $"{this.options.Value.AppBaseUri}/error", Height = TaskModuleHeight, Width = TaskModuleWidth, Title = this.localizer.GetString("ApplicationName"), }, }, }); } }