public async Task <ISpamOperatorResult <Reply> > UpdateModelAsync(ISpamOperatorContext <Reply> context) { // Perform validation var validation = await ValidateModelAsync(context); // Create result var result = new SpamOperatorResult <Reply>(); // Not an operator of interest if (validation == null) { return(result.Success(context.Model)); } // If validation succeeded no need to perform further actions if (validation.Succeeded) { return(result.Success(context.Model)); } // Get reply author var user = await BuildUserAsync(context.Model); if (user == null) { return(null); } // Flag user as SPAM? if (context.Operation.FlagAsSpam) { var bot = await _platoUserStore.GetPlatoBotAsync(); // Mark user as SPAM if (!user.IsSpam) { user.IsSpam = true; user.IsSpamUpdatedUserId = bot?.Id ?? 0; user.IsSpamUpdatedDate = DateTimeOffset.UtcNow; await _platoUserStore.UpdateAsync(user); } // Mark reply as SPAM if (!context.Model.IsSpam) { context.Model.IsSpam = true; await _replyStore.UpdateAsync(context.Model); } } // Defer notifications for execution after request completes _deferredTaskManager.AddTask(async ctx => { await NotifyAsync(context); }); // Return failed with our updated model and operation // This provides the calling code with the operation error message return(result.Failed(context.Model, context.Operation)); }
public async Task <TEntityReply> UpdateAsync(TEntityReply reply) { // Get aggregate rating var aggregateRating = await _entityRatingsAggregateStore.SelectAggregateRating(reply.EntityId, reply.Id); // Update entity reply.TotalRatings = aggregateRating?.TotalRatings ?? 0; reply.SummedRating = aggregateRating?.SummedRating ?? 0; reply.MeanRating = aggregateRating?.MeanRating ?? 0; // Update and return updated entity return(await _entityStore.UpdateAsync(reply)); }
async Task <IList <int> > SendNotificationsAsync(TEntityReply reply, IList <int> usersToExclude) { if (reply == null) { throw new ArgumentNullException(nameof(reply)); } // Compile a list of notified users var notifiedUsers = new List <int>(); // Follow type name var name = FollowTypes.Tag.Name; // Get follow state for reply var state = reply.GetOrCreate <FollowState>(); // Have notifications already been sent for the reply? var follow = state.FollowsSent.FirstOrDefault(f => f.Equals(name, StringComparison.InvariantCultureIgnoreCase)); if (follow != null) { return(notifiedUsers); } // Compile all entity tags ids for the entity var tags = new List <int>(); var entityTags = await _entityTagStore.GetByEntityReplyIdAsync(reply.Id); if (entityTags != null) { foreach (var entityTag in entityTags) { if (!tags.Contains(entityTag.TagId)) { tags.Add(entityTag.TagId); } } } // Get follows for all reply tags var follows = await _followStore.QueryAsync() .Select <FollowQueryParams>(q => { q.Name.Equals(name); q.ThingId.IsIn(tags.ToArray()); if (usersToExclude.Count > 0) { q.CreatedUserId.IsNotIn(usersToExclude.ToArray()); } }) .ToList(); // Reduce the users for all found follows var users = await ReduceUsersAsync(follows?.Data, reply); // No users simply return if (users == null) { return(notifiedUsers); } // Send notifications foreach (var user in users) { // Email notifications if (user.NotificationEnabled(_userNotificationTypeDefaults, EmailNotifications.NewReplyTag)) { // Track notified if (!notifiedUsers.Contains(user.Id)) { notifiedUsers.Add(user.Id); } // Notify await _notificationManager.SendAsync(new Notification(EmailNotifications.NewReplyTag) { To = user, }, reply); } // Web notifications if (user.NotificationEnabled(_userNotificationTypeDefaults, WebNotifications.NewReplyTag)) { // Track notified if (!notifiedUsers.Contains(user.Id)) { notifiedUsers.Add(user.Id); } // Notify await _notificationManager.SendAsync(new Notification(WebNotifications.NewReplyTag) { To = user, From = new User { Id = reply.CreatedBy.Id, UserName = reply.CreatedBy.UserName, DisplayName = reply.CreatedBy.DisplayName, Alias = reply.CreatedBy.Alias, PhotoUrl = reply.CreatedBy.PhotoUrl, PhotoColor = reply.CreatedBy.PhotoColor } }, reply); } } // Update state state.AddSent(name); reply.AddOrUpdate(state); // Persist state await _entityReplyStore.UpdateAsync(reply); // Return a list of all notified users return(notifiedUsers); }
// ----------- Task <TEntityReply> SendNotificationsAsync( TEntityReply reply, IList <int> usersToExclude) { if (reply == null) { throw new ArgumentNullException(nameof(reply)); } // The reply always need an entity Id if (reply.EntityId <= 0) { throw new ArgumentNullException(nameof(reply.EntityId)); } // No need to send notifications for hidden replies if (reply.IsHidden()) { return(Task.FromResult(reply)); } // Add deferred task _deferredTaskManager.AddTask(async context => { // Follow type name var name = FollowTypes.Idea.Name; // Get follow sent state for reply var state = reply.GetOrCreate <FollowState>(); // Have notifications already been sent for the reply? var follow = state.FollowsSent.FirstOrDefault(f => f.Equals(name, StringComparison.InvariantCultureIgnoreCase)); if (follow != null) { return; } // Get entity for reply var entity = await _entityStore.GetByIdAsync(reply.EntityId); // No need to send notifications if the entity is hidden if (entity.IsHidden()) { return; } // Get all follows for entity var follows = await _followStore.QueryAsync() .Select <FollowQueryParams>(q => { q.ThingId.Equals(reply.EntityId); q.Name.Equals(name); if (usersToExclude.Count > 0) { q.CreatedUserId.IsNotIn(usersToExclude.ToArray()); } }) .ToList(); // No follows simply return if (follows?.Data == null) { return; } // Get users var users = await ReduceUsersAsync(follows?.Data, reply); // We always need users if (users == null) { return; } // Send notifications foreach (var user in users) { // Email notifications if (user.NotificationEnabled(_userNotificationTypeDefaults, EmailNotifications.NewIdeaComment)) { await _notificationManager.SendAsync(new Notification(EmailNotifications.NewIdeaComment) { To = user, }, reply); } // Web notifications if (user.NotificationEnabled(_userNotificationTypeDefaults, WebNotifications.NewIdeaComment)) { await _notificationManager.SendAsync(new Notification(WebNotifications.NewIdeaComment) { To = user, From = new User() { Id = reply.CreatedBy.Id, UserName = reply.CreatedBy.UserName, DisplayName = reply.CreatedBy.DisplayName, Alias = reply.CreatedBy.Alias, PhotoUrl = reply.CreatedBy.PhotoUrl, PhotoColor = reply.CreatedBy.PhotoColor } }, reply); } } // Update sent state state.AddSent(name); reply.AddOrUpdate(state); // Persist state await _entityReplyStore.UpdateAsync(reply); }); return(Task.FromResult(reply)); }
// -------------------- async Task <ICommandResultBase> ApplyLatestHistoryPoint(Idea entity, IdeaComment reply) { // Get current user var user = await _contextFacade.GetAuthenticatedUserAsync(); // We need to be authenticated to make changes if (user == null) { return(await ResetEditDetails(entity, reply, user)); } // Get newest / most recent history entry var histories = await _entityHistoryStore.QueryAsync() .Take(1, false) .Select <EntityHistoryQueryParams>(q => { q.EntityId.Equals(entity.Id); q.EntityReplyId.Equals(reply?.Id ?? 0); }) .OrderBy("Id", OrderBy.Desc) .ToList(); // No history point, return success if (histories == null) { return(await ResetEditDetails(entity, reply, user)); } // No history point, return success if (histories.Data == null) { return(await ResetEditDetails(entity, reply, user)); } // No history point, return success if (histories.Data.Count == 0) { return(await ResetEditDetails(entity, reply, user)); } var history = histories.Data[0]; // No history available reset edit details if (history == null) { return(await ResetEditDetails(entity, reply, user)); } // Update edit details based on latest history point var result = new CommandResultBase(); if (reply != null) { reply.ModifiedUserId = user.Id; reply.ModifiedDate = DateTimeOffset.UtcNow; reply.EditedUserId = history.CreatedUserId; reply.EditedDate = history.CreatedDate; // Update reply to history point var updateResult = await _entityReplyStore.UpdateAsync(reply); if (updateResult != null) { return(result.Success()); } } else { entity.ModifiedUserId = user.Id; entity.ModifiedDate = DateTimeOffset.UtcNow; entity.EditedUserId = history.CreatedUserId; entity.EditedDate = history.CreatedDate; // Update entity to history point var updateResult = await _entityStore.UpdateAsync(entity); if (updateResult != null) { return(result.Success()); } } return(result.Success()); }
public async Task <ICommandResult <TReply> > UpdateAsync(TReply reply) { // Validate if (reply == null) { throw new ArgumentNullException(nameof(reply)); } if (reply.Id <= 0) { throw new ArgumentOutOfRangeException(nameof(reply.Id)); } if (reply.EntityId <= 0) { throw new ArgumentOutOfRangeException(nameof(reply.EntityId)); } if (String.IsNullOrWhiteSpace(reply.Message)) { throw new ArgumentNullException(nameof(reply.Message)); } //if (reply.ModifiedUserId <= 0) //{ // throw new ArgumentOutOfRangeException(nameof(reply.ModifiedUserId)); //} //if (reply.ModifiedDate == null) //{ // throw new ArgumentNullException(nameof(reply.ModifiedDate)); //} var result = new CommandResult <TReply>(); // Ensure entity exists var entity = await _entityStore.GetByIdAsync(reply.EntityId); if (entity == null) { return(result.Failed(new CommandError($"An entity with the Id '{reply.EntityId}' could not be found"))); } // Parse Html and message abstract reply.Html = await ParseEntityHtml(reply.Message); reply.Abstract = await ParseEntityAbstract(reply.Message); reply.Urls = await ParseEntityUrls(reply.Html); // Raise updating event Updating?.Invoke(this, new EntityReplyEventArgs <TReply>(entity, reply)); // Invoke EntityReplyUpdating subscriptions foreach (var handler in _broker.Pub <TReply>(this, "EntityReplyUpdating")) { reply = await handler.Invoke(new Message <TReply>(reply, this)); } var updatedReply = await _entityReplyStore.UpdateAsync(reply); if (updatedReply != null) { // Raise Updated event Updated?.Invoke(this, new EntityReplyEventArgs <TReply>(entity, updatedReply)); // Invoke EntityReplyUpdated subscriptions foreach (var handler in _broker.Pub <TReply>(this, "EntityReplyUpdated")) { updatedReply = await handler.Invoke(new Message <TReply>(updatedReply, this)); } return(result.Success(updatedReply)); } return(result.Failed(new CommandError("An unknown error occurred whilst attempting to update the reply."))); }