public void ReplyToThing(DB4Thing thing, string reply, bool isSticky = false) { var qualifiedThing = getQualifiedThing(thing); Task.Run(async() => { Comment newComment; if (qualifiedThing is Post post) { // Make a new comment newComment = await post.CommentAsync(reply); } else if (qualifiedThing is Comment comment) { // Reply to existing comment newComment = await comment.ReplyAsync(reply); } else { throw new InvalidOperationException($"Tried to reply to a Thing that isn't a Post or Comment - Thing ID: {qualifiedThing.Id}"); } // All DB4 replies should be distinguished await newComment.DistinguishAsync(ModeratableThing.DistinguishType.Moderator, isSticky); }).Wait(); }
private int performWikiPageUpdate(DB4Thing comment, bool isAward) { if (string.IsNullOrEmpty(_userWikiTemplate)) { _userWikiTemplate = File.ReadAllText(_appConfiguration.TemplateFiles.UserWikiTemplateFile); } if (string.IsNullOrEmpty(_userWikiRowTemplate)) { _userWikiRowTemplate = File.ReadAllText(_appConfiguration.TemplateFiles.UserWikiRowTemplateFile); } string givingUserUrl = getUserWikiUrl(comment.AuthorName); string receivingUserUrl = getUserWikiUrl(comment.ParentThing.AuthorName); // Get content for the user giving var givingInfo = buildUserPageContent(givingUserUrl, comment.AuthorName, comment.ParentThing.AuthorName, comment, true, isAward); // Get content for the user receiving var receivngInfo = buildUserPageContent(receivingUserUrl, comment.ParentThing.AuthorName, comment.AuthorName, comment, false, isAward); // Update content _subredditService.EditWikiPage(givingUserUrl, givingInfo.Item1, GiveEditReason); _subredditService.EditWikiPage(receivingUserUrl, receivngInfo.Item1, ReceiveEditReason); // We only care about the receiving count for updated flair return(receivngInfo.Item2); }
public void Process(DB4Thing privateMessage) { // If we got here with a comment or post, that's a problem Assert.That(privateMessage.Type == DB4ThingType.PrivateMessage, $"CommentProcessor received type: {privateMessage.Type}"); _logger.Info($"Processing incoming private message from: {privateMessage.AuthorName}, subject: {privateMessage.Subject}"); // Get a handler to handle this private message var handler = _privateMessageHandlerFactory.Create(privateMessage); // The handler could be null if this kind of private message doesn't have handler if (handler != null) { _logger.Info($"PrivateMessageHandler created: {handler.GetType()}"); try { // Try to handle the message handler.Handle(privateMessage); } catch (Exception) { // Remember to set message to read even if there was an exception _redditService.SetPrivateMessageAsRead(privateMessage.Id); // Re-throw - it will be handled and logged by dispatcher throw; } } // After handling the private message, set it to read _redditService.SetPrivateMessageAsRead(privateMessage.Id); _logger.Info("Done processing private message."); }
public DB4Comment BuildSticky(DB4Thing post, int deltaCount, WATTArticle article, string deltaLogPostUrl) { // Can only call BuildSticky on posts Assert.That(post.Type == DB4ThingType.Post); string body = string.Empty; if (deltaCount > 0) { body += _appConfiguration.Comments.PostStickyDeltas .Replace(_appConfiguration.ReplaceTokens.UsernameToken, post.AuthorName) .Replace(_appConfiguration.ReplaceTokens.CountToken, deltaCount.ToString()) .Replace(_appConfiguration.ReplaceTokens.PostLink, deltaLogPostUrl) .Replace(_appConfiguration.ReplaceTokens.DeltaLogSubredditToken, _appConfiguration.DeltaLogSubredditName); } if (article != null) { if (!string.IsNullOrEmpty(body)) { body += "\n\n"; } body += _appConfiguration.Comments.PostStickyWATT .Replace(_appConfiguration.ReplaceTokens.WATTLinkToken, article.Url); } return(new DB4Comment { CommentType = DB4CommentType.PostSticky, CommentBody = body }); }
public DB4ReplyResult DidDB4Reply(DB4Thing comment) { // Check for a reply in the immediate children of the comment foreach(DB4Thing childComment in comment.Comments) { if (childComment.AuthorName == _appConfiguration.DB4Username) { foreach (var reply in _allComments) { if (reply.Item2.IsMatch(childComment.Body)) { // The sticky comment should never be detected in a comment reply Assert.That(reply.Item1 != DB4CommentType.PostSticky); return new DB4ReplyResult { HasDB4Replied = true, CommentType = reply.Item1, Comment = childComment }; } } } } // DB4 hasn't replied yet return new DB4ReplyResult { HasDB4Replied = false }; }
public DB4Comment BuildReply(DB4CommentType commentType, DB4Thing comment) { // Can only call BuildReply on comments Assert.That(comment.Type == DB4ThingType.Comment); string body = string.Empty; switch (commentType) { case DB4CommentType.FailCommentTooShort: body = _appConfiguration.Comments.CommentTooShort.Replace(_appConfiguration.ReplaceTokens.ParentAuthorNameToken, comment.ParentThing.AuthorName); break; case DB4CommentType.FailCannotAwardOP: body = _appConfiguration.Comments.CannotAwardOP; break; case DB4CommentType.FailCannotAwardDeltaBot: body = _appConfiguration.Comments.CannotAwardDeltaBot; break; case DB4CommentType.FailCannotAwardSelf: body = _appConfiguration.Comments.CannotAwardSelf; break; case DB4CommentType.FailCannotAwardTwice: body = _appConfiguration.Comments.CannotAwardTwice .Replace(_appConfiguration.ReplaceTokens.ParentAuthorNameToken, comment.ParentThing.AuthorName); break; case DB4CommentType.ModeratorAdded: body = _appConfiguration.Comments.ModeratorAdded .Replace(_appConfiguration.ReplaceTokens.ParentAuthorNameToken, comment.ParentThing.AuthorName) .Replace(_appConfiguration.ReplaceTokens.SubredditToken, _appConfiguration.SubredditName) .Replace(_appConfiguration.ReplaceTokens.DeltasToken, (_userWikiEditor.GetCurrentDeltaCount(comment.ParentThing.AuthorName) + 1).ToString()); break; case DB4CommentType.ModeratorRemoved: body = _appConfiguration.Comments.ModeratorRemoved; break; case DB4CommentType.SuccessDeltaAwarded: body = _appConfiguration.Comments.DeltaAwarded .Replace(_appConfiguration.ReplaceTokens.ParentAuthorNameToken, comment.ParentThing.AuthorName) .Replace(_appConfiguration.ReplaceTokens.SubredditToken, _appConfiguration.SubredditName) .Replace(_appConfiguration.ReplaceTokens.DeltasToken, (_userWikiEditor.GetCurrentDeltaCount(comment.ParentThing.AuthorName) + 1).ToString()); break; default: throw new UnhandledEnumException <DB4CommentType>(commentType); } return(new DB4Comment { CommentType = commentType, CommentBody = body }); }
public void EditReply(DB4Thing commentToEdit, DB4Comment db4Comment) { string replyMessage = getReplyMessage(db4Comment); _redditService.EditComment(commentToEdit, replyMessage); _logger.Info($"DeltaBot edited a reply -> result: {db4Comment.CommentType.ToString()} link: {commentToEdit.Shortlink}"); }
public void Reply(DB4Thing thing, DB4Comment db4Comment, bool isSticky = false) { string replyMessage = getReplyMessage(db4Comment); _redditService.ReplyToThing(thing, replyMessage, isSticky); _logger.Info($"DeltaBot replied -> result: {db4Comment.CommentType.ToString()} link: {thing.Shortlink}"); }
public void EditComment(DB4Thing comment, string editedComment) { // Can only edit comments Assert.That(comment.Type == DB4ThingType.Comment); var qualifiedComment = (Comment)getQualifiedThing(comment); Task.Run(async() => await qualifiedComment.EditTextAsync(editedComment)).Wait(); }
public void DeleteComment(DB4Thing comment) { // Can only delete comments Assert.That(comment.Type == DB4ThingType.Comment); var qualifiedComment = (Comment)getQualifiedThing(comment); Task.Run(async() => await qualifiedComment.DelAsync()).Wait(); }
public void UpsertOrRemove(DB4Thing post, int?deltaCount, WATTArticle article, string deltaLogPostUrl) { // This method needs to do some extra work to handle WATT stuff // I'm not loving how this particular implementation came out... // Anyhow, we're expecting either a delta count from award / unaward OR a WATTArticle from a private message // Not both. if (deltaCount.HasValue && article != null) { throw new InvalidOperationException("Both a delta count and WATT article were provided when only one or the other was expected."); } // If we didn't get a delta count, look it up int finalDeltaCount; if (deltaCount.HasValue) { finalDeltaCount = deltaCount.Value; } else { finalDeltaCount = _repository.GetDeltaCommentsForPost(post.Id, post.AuthorName).Count; } // If we didn't get a WATT article, look it up // It's optional, so it could still be null after the lookup if (article == null) { article = _repository.GetWattArticleForPost(post.Id); } // Find out if the sticky comment has been made yet var result = _commentDetector.DidDB4MakeStickyComment(post); // During an Unaward, we can go down to zero. // If there are no deltas and no WATT article, delete the sticky if (deltaCount == 0 && article == null) { _commentReplier.DeleteReply(result.Comment); return; } // We'll need the updated sticky whether it has been made or not var db4Comment = _commentBuilder.BuildSticky(post, finalDeltaCount, article, deltaLogPostUrl); if (result.HasDB4Replied) { // Sticky exists, edit _commentReplier.EditReply(result.Comment, db4Comment); } else { // No sticky, create it _commentReplier.Reply(post, db4Comment, true); } }
public void Unaward(DB4Thing comment) { // This can happen on "force add" command if (comment.ParentThing.AuthorName == Constants.DeletedAuthorName) { _logger.Info("---SKIPPING UNAWARD ON DELETED USER---"); return; } _logger.Info($"---START UNAWARD DELTA--- -> user: {comment.ParentThing.AuthorName}, comment: {comment.Permalink}"); // Update wiki // The wiki is the standard from which delta counts come from _logger.Info(" ---Updating wiki (unaward)"); int newDeltaCount = _wikiEditor.UpdateUserWikiEntryUnaward(comment); string newFlairText = string.Empty; // If we are removing the user's only delta, we don't want the text to read "0∆" if (newDeltaCount != 0) { newFlairText = DeltaHelper.GetFlairText(newDeltaCount); } // Unaward from the parent comment _logger.Info(" ---Setting flair (unaward)"); _subredditService.SetUserFlair(comment.ParentThing.AuthorName, comment.ParentThing.AuthorFlairCssClass, newFlairText); // Update deltaboards _logger.Info(" ---Updating deltaboards (unaward)"); _deltaboardEditor.RemoveDelta(comment.ParentThing.AuthorName); // Remove from repository after successful unaward _logger.Info(" ---Removing delta from local db (unaward)"); _repository.RemoveDeltaComment(comment.Id); // Update DeltaLogs after repository update since it reads data from the repository _logger.Info(" ---Updating DeltaLog (unaward)"); string deltaLogPostUrl = _deltaLogEditor.Upsert(comment.ParentPost.Id, comment.ParentPost.Permalink, comment.ParentPost.Title, comment.ParentPost.AuthorName); // Update sticky if this is from OP if (comment.AuthorName == comment.ParentPost.AuthorName) { // We need to get the count of deltas for this particular post var opDeltaCommentsInPost = _repository.GetDeltaCommentsForPost(comment.ParentPost.Id, comment.ParentPost.AuthorName); // Update or remove sticky comment - make sure to remove one from the count since we haven't removed the data from // the repository yet, so the current comment won't count _logger.Info(" ---Updating post sticky (unaward)"); _stickyCommentEditor.UpsertOrRemove(comment.ParentPost, opDeltaCommentsInPost.Count, null, deltaLogPostUrl); } _logger.Info("---END UNAWARD DELTA---"); }
public void Handle(DB4Thing privateMessage) { // First split the PM up on newlines var privateMessageLines = privateMessage.Body.Split( new[] { "\r\n", "\r", "\n" }, StringSplitOptions.RemoveEmptyEntries); // We are expecting four lines // postid, postfullname, title, url // ex: // 8hr3tt // t3_8hr3tt // This is a WATT article // https://www.url.com if (privateMessageLines.Length != 4) { _redditService.ReplyToPrivateMessage(privateMessage.Id, CreateFailedInvalidFormatMessage); return; } // Create article string postId = privateMessageLines[0]; string postFullname = privateMessageLines[1]; string title = privateMessageLines[2]; string url = privateMessageLines[3]; var article = new WATTArticle { Id = Guid.NewGuid(), RedditPostId = postId, Title = title, Url = url }; // Save article _db4Repository.UpsertWATTArticle(article); // Need to retrieve the full post to make life easy var post = _redditService.GetThingByFullname(postFullname); _redditService.PopulateChildren(post); // Get DeltaLog mapping for building out sticky // The mapping can be null var deltaLogMapping = _db4Repository.GetDeltaLogPostMapping(postId); string deltaLogPostUrl = string.Empty; if (deltaLogMapping != null) { deltaLogPostUrl = deltaLogMapping.DeltaLogPostUrl; } // Update sticky for the post in question _stickyCommentEditor.UpsertOrRemove(post, null, article, deltaLogPostUrl); }
public void Handle(DB4Thing privateMessage) { // Check for a "stop" message if (privateMessage.Body.ToLower().Contains(StopIndicator)) { // Ignore user _db4Repository.AddIgnoredQuotedDeltaPMUser(privateMessage.AuthorName); // Send confirmation message _redditService.ReplyToPrivateMessage(privateMessage.Id, _appConfiguration.PrivateMessages.ConfirmStopQuotedDeltaWarningMessage); } }
private UserWikiDeltaInfo getUserWikiDeltaInfo(DB4Thing comment, DB4Thing parentPost, string toUsername) { string postLink = $"{_appConfiguration.RedditBaseUrl}{parentPost.Permalink}"; string postTitle = parentPost.Title; string createdUTC = new DateTimeOffset(comment.CreatedUtc).ToUnixTimeSeconds().ToString(); // Create new hidden param entry from comment return(new UserWikiDeltaInfo { PostLink = postLink, PostTitle = postTitle, CommentId = comment.Id, Username = toUsername, CreatedUTC = createdUTC }); }
private DB4Comment validateAndAward(DB4Thing qualifiedComment) { // Validate comment var commentValidationResult = _commentValidator.Validate(qualifiedComment); if (commentValidationResult.IsValidDelta) { // Award the delta // parentThing must be a Comment here - deltas are only // valid when the parent is a Comment Assert.That(qualifiedComment.ParentThing.Type == DB4ThingType.Comment); _deltaAwarder.Award(qualifiedComment); } return(commentValidationResult); }
public IPrivateMessageHandler Create(DB4Thing privateMessage) { // Some private messages don't have an author. All handlers here // require an author to process. if (string.IsNullOrEmpty(privateMessage.AuthorName)) { return(null); } // Add Delta (moderator only) if (_subredditService.IsUserModerator(privateMessage.AuthorName) && string.Equals(privateMessage.Subject, _appConfiguration.PrivateMessages.ModAddDeltaSubject, StringComparison.CurrentCultureIgnoreCase)) { return(new ModAddDeltaPMHandler(_appConfiguration, _redditService, _commentDetector, _commentBuilder, _replier, _deltaAwarder)); } // Force Add Delta (moderator only) if (_subredditService.IsUserModerator(privateMessage.AuthorName) && string.Equals(privateMessage.Subject, _appConfiguration.PrivateMessages.ModForceAddDeltaSubject, StringComparison.CurrentCultureIgnoreCase)) { return(new ModForceAddDeltaPMHandler(_appConfiguration, _redditService, _commentDetector, _commentBuilder, _replier, _deltaAwarder)); } // Remove delta (moderator only) if (_subredditService.IsUserModerator(privateMessage.AuthorName) && string.Equals(privateMessage.Subject, _appConfiguration.PrivateMessages.ModDeleteDeltaSubject, StringComparison.CurrentCultureIgnoreCase)) { return(new ModDeleteDeltaPMHandler(_appConfiguration, _redditService, _commentDetector, _commentBuilder, _replier, _deltaAwarder)); } // Stop quoted deltas warning if (string.Equals(privateMessage.Subject, _appConfiguration.PrivateMessages.DeltaInQuoteSubject, StringComparison.CurrentCultureIgnoreCase)) { return(new StopQuotedDeltaWarningsPMHandler(_appConfiguration, _db4Repository, _redditService)); } // WATT Article created (author must be in ValidWATTUsers list) if (_appConfiguration.ValidWATTUsers.Any(u => string.Equals(u, privateMessage.AuthorName, StringComparison.CurrentCultureIgnoreCase)) && string.Equals(privateMessage.Subject, _appConfiguration.PrivateMessages.WATTArticleCreatedSubject, StringComparison.CurrentCultureIgnoreCase)) { return(new WATTArticleCreatedPMHandler(_db4Repository, _redditService, _stickyCommentEditor)); } return(null); }
public void PopulateChildren(DB4Thing post) { // PopulateChildren should only be called on posts Assert.That(post.Type == DB4ThingType.Post); var qualifiedPost = (Post)getQualifiedThing(post); post.Comments = new List <DB4Thing>(); Task.Run(async() => { var postComments = await qualifiedPost.GetCommentsAsync(); foreach (var postComment in postComments) { post.Comments.Add(RedditThingConverter.Convert(postComment)); } }).Wait(); }
public void PopulateParentAndChildren(DB4Thing comment) { // PopulateParentAndChildren should only be called on comments Assert.That(comment.Type == DB4ThingType.Comment); // Get comment with children and parent post populated var qualifiedComment = (Comment)getQualifiedThing(comment); // Set parent post comment.ParentPost = RedditThingConverter.Convert(qualifiedComment.Parent); // We also want all of the immediate children (comments) of a Post if (qualifiedComment.Parent is Post parentPost) { comment.ParentPost.Comments = new List <DB4Thing>(); Task.Run(async() => { var postComments = await parentPost.GetCommentsAsync(); foreach (var postComment in postComments) { comment.ParentPost.Comments.Add(RedditThingConverter.Convert(postComment)); } }).Wait(); } // Convert immediate children only var childComments = new List <DB4Thing>(); foreach (Comment childComment in qualifiedComment.Comments) { childComments.Add(RedditThingConverter.Convert(childComment)); } comment.Comments = childComments; // Get the parent thing - this could be the same as ParentPost above or it could be a comment var parentThing = _reddit.GetThingByFullnameAsync(comment.ParentId).Result; comment.ParentThing = RedditThingConverter.Convert(parentThing); }
public DB4Comment Validate(DB4Thing comment) { // The immediate parent thing must be a comment (not a post) to be eligible if (comment.ParentThing.Type == DB4ThingType.Post) { return(_commentBuilder.BuildReply(DB4CommentType.FailCannotAwardOP, comment)); } // Cannot award self if (comment.ParentThing.AuthorName == comment.AuthorName) { return(_commentBuilder.BuildReply(DB4CommentType.FailCannotAwardSelf, comment)); } // Cannot award OP if (comment.ParentThing.AuthorName == comment.ParentPost.AuthorName) { return(_commentBuilder.BuildReply(DB4CommentType.FailCannotAwardOP, comment)); } // Cannot award twice for same comment if (_db4Repository.DeltaCommentExistsForParentCommentByAuthor(comment.ParentId, comment.AuthorName)) { return(_commentBuilder.BuildReply(DB4CommentType.FailCannotAwardTwice, comment)); } // Cannot award DeltaBot if (comment.ParentThing.AuthorName == _appConfiguration.DB4Username) { return(_commentBuilder.BuildReply(DB4CommentType.FailCannotAwardDeltaBot, comment)); } // Check comment length if (comment.Body.Length < _appConfiguration.ValidationValues.CommentTooShortLength) { return(_commentBuilder.BuildReply(DB4CommentType.FailCommentTooShort, comment)); } // Success - valid delta return(_commentBuilder.BuildReply(DB4CommentType.SuccessDeltaAwarded, comment)); }
private Thing getQualifiedThing(DB4Thing thing) { var link = thing.Type == DB4ThingType.Comment ? thing.Shortlink : thing.Permalink; string thingUrl = $"{UrlHelper.OAuthRedditBaseUrl}{link}".TrimEnd('/'); var thingUri = new Uri(thingUrl); switch (thing.Type) { case DB4ThingType.Comment: // Get comment with children and parent post populated return(_reddit.GetCommentAsync(thingUri).Result); case DB4ThingType.Post: // Get post return(_reddit.GetPostAsync(thingUri).Result); default: throw new UnhandledEnumException <DB4ThingType>(thing.Type); } }
public DB4ReplyResult DidDB4MakeStickyComment(DB4Thing post) { var sticky = _allComments.First(c => c.Item1 == DB4CommentType.PostSticky); foreach (DB4Thing childComment in post.Comments) { if (childComment.AuthorName == _appConfiguration.DB4Username && sticky.Item2.IsMatch(childComment.Body)) { return new DB4ReplyResult { HasDB4Replied = true, CommentType = DB4CommentType.PostSticky, Comment = childComment }; } } // No sticky return new DB4ReplyResult { HasDB4Replied = false }; }
private (string, int) buildUserPageContent(string userUrl, string username, string toUsername, DB4Thing commentToBuildLinkFor, bool giving, bool isAward) { // Load hidden params from the wiki page. This will create hiddenparams for a new page var wikiHiddenParams = getHiddenParams(userUrl, toUsername); if (wikiHiddenParams.DeltasGiven == null) { wikiHiddenParams.DeltasGiven = new List <UserWikiDeltaInfo>(); } if (wikiHiddenParams.DeltasReceived == null) { wikiHiddenParams.DeltasReceived = new List <UserWikiDeltaInfo>(); } // Add new info to hidden params if (giving) { if (isAward) { // Award delta given wikiHiddenParams.DeltasGiven.Add(getUserWikiDeltaInfo(commentToBuildLinkFor, commentToBuildLinkFor.ParentPost, toUsername)); } else { // Unaward delta given UserWikiDeltaInfo deltaInfo = wikiHiddenParams.DeltasGiven.First(d => d.CommentId == commentToBuildLinkFor.Id); wikiHiddenParams.DeltasGiven.Remove(deltaInfo); } } else { if (isAward) { // Award delta received wikiHiddenParams.DeltasReceived.Add(getUserWikiDeltaInfo(commentToBuildLinkFor, commentToBuildLinkFor.ParentPost, toUsername)); } else { // Unaward delta received UserWikiDeltaInfo deltaInfo = wikiHiddenParams.DeltasReceived.First(d => d.CommentId == commentToBuildLinkFor.Id); wikiHiddenParams.DeltasReceived.Remove(deltaInfo); } } // Reconstruct content based on hidden params string updatedContent = _userWikiTemplate; // Replace the hidden params token with the new serialized hidden params string hiddenParamsJson = JsonConvert.SerializeObject(wikiHiddenParams, Formatting.Indented) .Replace("(", ParenOpenToken) .Replace(")", ParenCloseToken); updatedContent = updatedContent .Replace(_appConfiguration.ReplaceTokens.HiddenParamsToken, hiddenParamsJson) .Replace(_appConfiguration.ReplaceTokens.UsernameToken, username) .Replace(_appConfiguration.ReplaceTokens.DeltasGivenCountToken, wikiHiddenParams.DeltasGiven.Count.ToString()) .Replace(_appConfiguration.ReplaceTokens.DeltasReceivedCountToken, wikiHiddenParams.DeltasReceived.Count.ToString()); // Update rows string givingRowsContent = getRowsContent(wikiHiddenParams.DeltasGiven, "3"); string receivingRowsContent = getRowsContent(wikiHiddenParams.DeltasReceived, "2"); updatedContent = updatedContent .Replace(_appConfiguration.ReplaceTokens.WikiRowsGivenToken, givingRowsContent) .Replace(_appConfiguration.ReplaceTokens.WikiRowsReceivedToken, receivingRowsContent); return(updatedContent, wikiHiddenParams.DeltasReceived.Count); }
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 int UpdateUserWikiEntryUnaward(DB4Thing comment) { return(performWikiPageUpdate(comment, false)); }
public int UpdateUserWikiEntryAward(DB4Thing comment) { return(performWikiPageUpdate(comment, true)); }
public void Award(DB4Thing comment) { // This can happen on "force add" command if (comment.ParentThing.AuthorName == Constants.DeletedAuthorName) { _logger.Info("---SKIPPING AWARD ON DELETED USER---"); return; } _logger.Info($"---START AWARD DELTA--- -> user: {comment.ParentThing.AuthorName}, comment: {comment.Permalink}"); // Update wiki // The wiki is the standard from which delta counts come from _logger.Info(" ---Updating wiki (award)"); int newDeltaCount = _wikiEditor.UpdateUserWikiEntryAward(comment); // If this was the user's first delta, send the first delta PM if (newDeltaCount == 1) { string subject = _appConfiguration.PrivateMessages.FirstDeltaSubject; string body = _appConfiguration.PrivateMessages.FirstDeltaMessage .Replace(_appConfiguration.ReplaceTokens.SubredditToken, _appConfiguration.SubredditName) .Replace(_appConfiguration.ReplaceTokens.UsernameToken, comment.ParentThing.AuthorName); _logger.Info(" ---Sending first delta PM (award)"); _redditService.SendPrivateMessage(subject, body, comment.ParentThing.AuthorName); } // Get new flair with incremented delta count string newFlairText = DeltaHelper.GetFlairText(newDeltaCount); // Award to the parent comment _logger.Info(" ---Setting flair (award)"); _subredditService.SetUserFlair(comment.ParentThing.AuthorName, comment.ParentThing.AuthorFlairCssClass, newFlairText); // Update deltaboards _logger.Info(" ---Updating deltaboards (award)"); _deltaboardEditor.AddDelta(comment.ParentThing.AuthorName); // After a successful award, record the DeltaComment var deltaComment = new DeltaComment { Id = comment.Id, ParentId = comment.ParentId, CreatedUtc = comment.CreatedUtc, IsEdited = comment.IsEdited, FromUsername = comment.AuthorName, ToUsername = comment.ParentThing.AuthorName, CommentText = comment.ParentThing.Body, LinkId = comment.LinkId, Permalink = comment.Permalink, Shortlink = comment.Shortlink, ParentPostId = comment.ParentPost.Id, ParentPostLinkId = comment.ParentPost.LinkId, ParentPostPermalink = comment.ParentPost.Permalink, ParentPostShortlink = comment.ParentPost.Shortlink, ParentPostTitle = comment.ParentPost.Title }; // Upsert performs an insert or update depending on if it already exists _logger.Info(" ---Adding delta to local db (award)"); _repository.UpsertDeltaComment(deltaComment); // Update DeltaLogs after repository update since it reads data from the repository _logger.Info(" ---Updating DeltaLog (award)"); string deltaLogPostUrl = _deltaLogEditor.Upsert(comment.ParentPost.Id, comment.ParentPost.Permalink, comment.ParentPost.Title, comment.ParentPost.AuthorName); // Update sticky if this is OP // This needs to be absolute last since it relies on getting a Url from the DeltaLog post if (comment.AuthorName == comment.ParentPost.AuthorName) { // We need to get the count of deltas for this particular post var opDeltaCommentsInPost = _repository.GetDeltaCommentsForPost(comment.ParentPost.Id, comment.ParentPost.AuthorName); // Update sticky comment _logger.Info(" ---Updating post sticky (award)"); _stickyCommentEditor.UpsertOrRemove(comment.ParentPost, opDeltaCommentsInPost.Count, null, deltaLogPostUrl); } _logger.Info("---END AWARD DELTA---"); }
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; } }
private void pushToQueue(DB4Thing db4Thing, QueueMessageType messageType) { // Put on the queue for comment processing _queue.Push(new QueueMessage(messageType, JsonConvert.SerializeObject(db4Thing), DateTime.UtcNow)); }
public void DeleteReply(DB4Thing commentToDelete) { _redditService.DeleteComment(commentToDelete); _logger.Info($"DeltaBot deleted a reply -> link: {commentToDelete.Shortlink}"); }