Beispiel #1
0
        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();
        }
Beispiel #2
0
        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);
        }
Beispiel #3
0
        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.");
        }
Beispiel #4
0
        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
            };
        }
Beispiel #6
0
        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
            });
        }
Beispiel #7
0
        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}");
        }
Beispiel #8
0
        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();
        }
Beispiel #10
0
        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);
            }
        }
Beispiel #12
0
        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---");
        }
Beispiel #13
0
        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);
            }
        }
Beispiel #15
0
        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);
        }
Beispiel #17
0
        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);
        }
Beispiel #18
0
        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();
        }
Beispiel #19
0
        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);
        }
Beispiel #20
0
        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));
        }
Beispiel #21
0
        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
            };
        }
Beispiel #23
0
        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);
        }
Beispiel #24
0
        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;
            }
        }
Beispiel #25
0
 public int UpdateUserWikiEntryUnaward(DB4Thing comment)
 {
     return(performWikiPageUpdate(comment, false));
 }
Beispiel #26
0
 public int UpdateUserWikiEntryAward(DB4Thing comment)
 {
     return(performWikiPageUpdate(comment, true));
 }
Beispiel #27
0
        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;
            }
        }
Beispiel #29
0
 private void pushToQueue(DB4Thing db4Thing, QueueMessageType messageType)
 {
     // Put on the queue for comment processing
     _queue.Push(new QueueMessage(messageType, JsonConvert.SerializeObject(db4Thing), DateTime.UtcNow));
 }
Beispiel #30
0
        public void DeleteReply(DB4Thing commentToDelete)
        {
            _redditService.DeleteComment(commentToDelete);

            _logger.Info($"DeltaBot deleted a reply -> link: {commentToDelete.Shortlink}");
        }