public void Handle(DB4Thing privateMessage) { // The body should be the URL to a comment string commentUrl = privateMessage.Body.Trim(); try { // Get comment by url var comment = _redditService.GetCommentByUrl(commentUrl); // If that succeeded, we need the full comment with children to check for replies _redditService.PopulateParentAndChildren(comment); // Check for replies var db4ReplyResult = _commentDetector.DidDB4Reply(comment); // If a the parent authorname is DeltaBot, bail if (comment.ParentThing.AuthorName == _appConfiguration.DB4Username) { _redditService.ReplyToPrivateMessage(privateMessage.Id, AddFailedCantAwardDeltaBot); return; } // If a the parent authorname is [deleted], bail if (comment.ParentThing.AuthorName == Constants.DeletedAuthorName) { _redditService.ReplyToPrivateMessage(privateMessage.Id, AddFailedAuthorDeletedMessage); return; } // If a delta was already awarded successfully, bail if (db4ReplyResult.HasDB4Replied && db4ReplyResult.WasSuccessReply || db4ReplyResult.CommentType == DB4CommentType.ModeratorAdded) { _redditService.ReplyToPrivateMessage(privateMessage.Id, AddFailedAlreadyAwardedMessage); return; } // Build the normal success message // IMPORTANT: Build reply *before* awarding. This has to do with a quirk with getting the correct // delta count to build the reply. My bad... var reply = _commentBuilder.BuildReply(DB4CommentType.SuccessDeltaAwarded, comment); // Award delta _deltaAwarder.Award(comment); // Don't edit the existing comment - delete it and reply with the mod added reply // db4ReplyResult.Comment will be null if the mod is adding a delta directly to a comment if (db4ReplyResult.Comment != null) { _replier.DeleteReply(db4ReplyResult.Comment); } _replier.Reply(comment, reply); // Build modmail body string body = _appConfiguration.PrivateMessages.ModAddedDeltaNotificationMessage .Replace(_appConfiguration.ReplaceTokens.UsernameToken, privateMessage.AuthorName) .Replace(_appConfiguration.ReplaceTokens.CommentLink, commentUrl); // Reply with modmail indicating success _redditService.SendPrivateMessage(_appConfiguration.PrivateMessages.ModAddedDeltaNotificationSubject, body, $"/r/{_appConfiguration.SubredditName}"); // Reply to user _redditService.ReplyToPrivateMessage(privateMessage.Id, AddSucceededMessage); } catch (Exception ex) { // Reply indicating failure _redditService.ReplyToPrivateMessage(privateMessage.Id, string.Format(AddFailedErrorMessageFormat, ex.ToString())); // Rethrow for logging purposes throw; } }
public void Handle(DB4Thing privateMessage) { // The body should be the URL to a comment string commentUrl = privateMessage.Body.Trim(); try { // Get comment by url var comment = _redditService.GetCommentByUrl(commentUrl); // If that succeeded, we need the full comment with children to check for replies _redditService.PopulateParentAndChildren(comment); // Check for replies var db4ReplyResult = _commentDetector.DidDB4Reply(comment); // If a the parent authorname is [deleted], bail if (comment.ParentThing.AuthorName == Constants.DeletedAuthorName) { _redditService.ReplyToPrivateMessage(privateMessage.Id, DeleteFailedAuthorDeletedMessage); return; } // If a delta was never awarded in the first place, bail if (!db4ReplyResult.HasDB4Replied || !db4ReplyResult.WasSuccessReply && db4ReplyResult.CommentType != DB4CommentType.ModeratorAdded) { _redditService.ReplyToPrivateMessage(privateMessage.Id, DeleteFailedNeverAwardedMessage); return; } // A delta was awarded, unaward it _deltaAwarder.Unaward(comment); // Build moderator removal message var reply = _commentBuilder.BuildReply(DB4CommentType.ModeratorRemoved, comment); // Don't edit the success comment - delete it and reply with the mod deleted reply _replier.DeleteReply(db4ReplyResult.Comment); _replier.Reply(comment, reply); // Build modmail body string body = _appConfiguration.PrivateMessages.ModDeletedDeltaNotificationMessage .Replace(_appConfiguration.ReplaceTokens.UsernameToken, privateMessage.AuthorName) .Replace(_appConfiguration.ReplaceTokens.CommentLink, commentUrl); // Reply with modmail indicating success _redditService.SendPrivateMessage(_appConfiguration.PrivateMessages.ModDeletedDeltaNotificationSubject, body, $"/r/{_appConfiguration.SubredditName}"); // Reply to user _redditService.ReplyToPrivateMessage(privateMessage.Id, DeleteSucceededMessage); } catch (Exception ex) { // Reply indicating failure _redditService.ReplyToPrivateMessage(privateMessage.Id, string.Format(DeleteFailedErrorMessageFormat, ex.ToString())); // Rethrow for logging purposes throw; } }
public void Process(DB4Thing comment) { // If we got here with a PM or post, that's a problem Assert.That(comment.Type == DB4ThingType.Comment, $"CommentProcessor received type: {comment.Type}"); _logger.Info($"Processing incoming comment{(comment.IsEdited ? " (edit)" : string.Empty)}: {comment.Permalink}"); // DB4 shouldn't process its own comments if (comment.AuthorName == _appConfiguration.DB4Username) { _logger.Info($"Done processing comment{(comment.IsEdited ? " (edit)" : string.Empty)}."); return; } // Comments with ninja edits will need to be refreshed if (comment.NeedsRefresh) { // Get latest comment and make sure to treat this as an edit // so the potential unaward code path is processed comment = _redditService.GetThingByFullname(comment.FullName); comment.IsEdited = true; } // Check for a delta bool hasDelta = commentHasDelta(comment.Body, out bool hadDeltaInQuotes); // If there was no legitimate delta, but there was a delta in quotes, PM // the user to let them know in case they made a mistake with reddit quoting if (!hasDelta && hadDeltaInQuotes && !_db4Repository.GetIgnoreQuotedDeltaPMUserList().Contains(comment.AuthorName)) { string subject = _appConfiguration.PrivateMessages.DeltaInQuoteSubject; string body = _appConfiguration.PrivateMessages.DeltaInQuoteMessage .Replace(_appConfiguration.ReplaceTokens.UsernameToken, comment.AuthorName) .Replace(_appConfiguration.ReplaceTokens.SubredditToken, _appConfiguration.SubredditName); _redditService.SendPrivateMessage(subject, body, comment.AuthorName); } if (hasDelta || comment.IsEdited) { // There is a delta or this comment is edited // We need to get more info for processing _redditService.PopulateParentAndChildren(comment); if (hasDelta) { // Check to see if db4 has already replied var db4ReplyResult = _commentDetector.DidDB4Reply(comment); // If DB4 hasn't replied, or if it did but this is an edit, perform comment logic if (!db4ReplyResult.HasDB4Replied) { // Validate comment and award delta if successful var commentValidationResult = validateAndAward(comment); // Post a reply with the result _commentReplier.Reply(comment, commentValidationResult); } else { // DB4 already replied. If DB4's reply was a fail reply, check to see if this delta // now passes validation (re-check edits). If it does, edit the old reply to be a success reply // NOTE: Moderator replies (force add / remove) won't be processed if (!db4ReplyResult.WasSuccessReply && !db4ReplyResult.WasModeratorReply) { // Validate comment and award delta if successful var commentValidationResult = validateAndAward(comment); // Edit the result to reflect new delta comment _commentReplier.EditReply(db4ReplyResult.Comment, commentValidationResult); } } } else if (comment.IsEdited) { // There is no delta. Check if DB4 replied. This means that // there was a delta previously. If the comment is less than HoursToRemoveDelta hours old, the delta // can be removed. // Check to see if db4 has replied var db4ReplyResult = _commentDetector.DidDB4Reply(comment); // If DB4 replied and awarded a delta in the last HoursToUnawardDelta, unaward it if (db4ReplyResult.HasDB4Replied && db4ReplyResult.WasSuccessReply && (DateTime.UtcNow - comment.CreatedUtc).TotalHours < _appConfiguration.HoursToUnawardDelta) { // Unaward // parentThing can safely be cast to Comment here - we could have only // gotten here if a delta was previously awarded, meaning the parent of this // Comment is a Comment also Assert.That(comment.ParentThing.Type == DB4ThingType.Comment); _deltaAwarder.Unaward(comment); // Delete award comment _commentReplier.DeleteReply(db4ReplyResult.Comment); } else if (db4ReplyResult.HasDB4Replied && !db4ReplyResult.WasSuccessReply) { // DB4 replied and it was a failure reply. Now there's no delta. // The user just removed the delta with their edit, so delete the reply _commentReplier.DeleteReply(db4ReplyResult.Comment); } } } _logger.Info($"Done processing comment{(comment.IsEdited ? " (edit)" : string.Empty)}."); }