Esempio n. 1
0
        public async Task <IHttpActionResult> CreateOne([NotNull] ActivityCommentCreateOneRequestDto requestDto)
        {
            var activity = await _dbContext.Activities.Include(a => a.Author)
                           .Where(a => a.Id == requestDto.ActivityId)
                           .SingleOrDefaultAsync();

            if (activity == null)
            {
                return(this.BadRequest(nameof(requestDto), nameof(requestDto.ActivityId), Errors.NonExistent));
            }

            var userId = User.Identity.GetUserId();

            if (activity.Archived != ArchivedState.None &&
                userId != activity.AuthorId && !User.IsInRole(KeylolRoles.Operator))
            {
                return(Unauthorized());
            }

            var comment = new Models.ActivityComment
            {
                ActivityId     = activity.Id,
                CommentatorId  = userId,
                Content        = requestDto.Content,
                SidForActivity = await _dbContext.ActivityComments.Where(c => c.ActivityId == activity.Id)
                                 .Select(c => c.SidForActivity)
                                 .DefaultIfEmpty(0)
                                 .MaxAsync() + 1
            };

            _dbContext.ActivityComments.Add(comment);
            await _dbContext.SaveChangesAsync();

            await _cachedData.ActivityComments.IncreaseActivityCommentCountAsync(activity.Id, 1);

            var messageNotifiedActivityAuthor = false;
            var steamNotifiedActivityAuthor   = false;
            var truncatedContent = comment.Content.Length > 512
                ? $"{comment.Content.Substring(0, 512)} …"
                : comment.Content;
            var activityContent = PostOfficeMessageList.CollapseActivityContent(activity);

            var matches = Regex.Matches(comment.Content, "^(?:#(\\d+)[ \\t]*)+(?:$|[ \\t]+)", RegexOptions.Multiline);

            if (matches.Count > 0)
            {
                var sidForActivities = (from Match match in matches
                                        from Capture capture in match.Groups[1].Captures
                                        select int.Parse(capture.Value)).ToList();

                var replyToComments = await _dbContext.ActivityComments
                                      .Include(c => c.Commentator)
                                      .Where(c => c.ActivityId == activity.Id && sidForActivities.Contains(c.SidForActivity))
                                      .ToListAsync();

                foreach (var replyToComment in replyToComments)
                {
                    _dbContext.Replies.Add(new Reply
                    {
                        EntryType = ReplyEntryType.ActivityComment,
                        EntryId   = replyToComment.Id,
                        ReplyId   = comment.Id
                    });
                }
                await _dbContext.SaveChangesAsync();

                foreach (var replyToUser in replyToComments
                         .Where(c => c.CommentatorId != comment.CommentatorId && !c.DismissReplyMessage)
                         .Select(c => c.Commentator).Distinct())
                {
                    if (replyToUser.NotifyOnCommentReplied)
                    {
                        messageNotifiedActivityAuthor = replyToUser.Id == activity.AuthorId;
                        await _cachedData.Messages.AddAsync(new Message
                        {
                            Type              = MessageType.ActivityCommentReply,
                            OperatorId        = comment.CommentatorId,
                            ReceiverId        = replyToUser.Id,
                            ActivityCommentId = comment.Id
                        });
                    }

                    if (replyToUser.SteamNotifyOnCommentReplied)
                    {
                        steamNotifiedActivityAuthor = replyToUser.Id == activity.AuthorId;
                        await _userManager.SendSteamChatMessageAsync(replyToUser,
                                                                     $"{comment.Commentator.UserName} 回复了你在「{activityContent}」下的评论:\n\n{truncatedContent}\n\nhttps://www.keylol.com/activity/{activity.Author.IdCode}/{activity.SidForAuthor}#{comment.SidForActivity}");
                    }
                }
            }

            if (comment.CommentatorId != activity.AuthorId && !activity.DismissCommentMessage)
            {
                if (!messageNotifiedActivityAuthor && activity.Author.NotifyOnActivityReplied)
                {
                    await _cachedData.Messages.AddAsync(new Message
                    {
                        Type              = MessageType.ActivityComment,
                        OperatorId        = comment.CommentatorId,
                        ReceiverId        = activity.AuthorId,
                        ActivityCommentId = comment.Id
                    });
                }

                if (!steamNotifiedActivityAuthor && activity.Author.SteamNotifyOnActivityReplied)
                {
                    await _userManager.SendSteamChatMessageAsync(activity.Author,
                                                                 $"{comment.Commentator.UserName} 评论了你的动态「{activityContent}」:\n\n{truncatedContent}\n\nhttps://www.keylol.com/activity/{activity.Author.IdCode}/{activity.SidForAuthor}#{comment.SidForActivity}");
                }
            }

            return(Ok(comment.SidForActivity));
        }
        public async Task <IHttpActionResult> UpdoteOneModeration(string id,
                                                                  [NotNull] ActivityCommentUpdateOneModerationRequestDto requestDto)
        {
            var comment = await _dbContext.ActivityComments.Include(c => c.Commentator).Include(c => c.Activity)
                          .Where(a => a.Id == id).SingleOrDefaultAsync();

            if (comment == null)
            {
                return(NotFound());
            }

            var operatorId       = User.Identity.GetUserId();
            var isKeylolOperator = User.IsInRole(KeylolRoles.Operator);

            if (!isKeylolOperator)
            {
                switch (requestDto.Property)
                {
                case ActivityCommentUpdateOneModerationRequestDto.CommentProperty.Archived:
                    if (comment.CommentatorId != operatorId)
                    {
                        return(Unauthorized());
                    }
                    break;

                default:
                    return(Unauthorized());
                }
            }

            if (
                !Enum.IsDefined(typeof(ActivityCommentUpdateOneModerationRequestDto.CommentProperty),
                                requestDto.Property))
            {
                throw new ArgumentOutOfRangeException(nameof(requestDto.Property));
            }
            var propertyInfo = typeof(Models.ActivityComment).GetProperty(requestDto.Property.ToString());

            if (requestDto.Property == ActivityCommentUpdateOneModerationRequestDto.CommentProperty.Archived)
            {
                if (comment.Archived != ArchivedState.None == requestDto.Value)
                {
                    return(this.BadRequest(nameof(requestDto), nameof(requestDto.Value), Errors.Duplicate));
                }

                if (isKeylolOperator)
                {
                    comment.Archived = requestDto.Value ? ArchivedState.Operator : ArchivedState.None;
                }
                else
                {
                    if (comment.Archived == ArchivedState.Operator)
                    {
                        return(Unauthorized());
                    }
                    comment.Archived = requestDto.Value ? ArchivedState.User : ArchivedState.None;
                }
            }
            else
            {
                if ((bool)propertyInfo.GetValue(comment) == requestDto.Value)
                {
                    return(this.BadRequest(nameof(requestDto), nameof(requestDto.Value), Errors.Duplicate));
                }

                propertyInfo.SetValue(comment, requestDto.Value);
            }
            await _dbContext.SaveChangesAsync();

            if (isKeylolOperator && (requestDto.NotifyAuthor ?? false))
            {
                var missive = new Message
                {
                    OperatorId        = operatorId,
                    ReceiverId        = comment.CommentatorId,
                    ActivityCommentId = comment.Id
                };
                string steamNotityText = null;
                var    activitySummary = PostOfficeMessageList.CollapseActivityContent(comment.Activity, 30);
                var    commentSummary  = comment.Content.Length > 30
                    ? $"{comment.Content.Substring(0, 30)} …"
                    : comment.Content;
                if (requestDto.Value)
                {
                    switch (requestDto.Property)
                    {
                    case ActivityCommentUpdateOneModerationRequestDto.CommentProperty.Archived:
                        missive.Type = MessageType.ActivityCommentArchive;
                        if (requestDto.Reasons != null)
                        {
                            missive.Reasons = string.Join(",", requestDto.Reasons);
                        }
                        steamNotityText =
                            $"动态「{activitySummary}」中的评论「{commentSummary}」已被封存,封存后此则评论的内容和作者信息会被隐藏。";
                        break;

                    case ActivityCommentUpdateOneModerationRequestDto.CommentProperty.Warned:
                        missive.Type = MessageType.ActivityCommentWarning;
                        if (requestDto.Reasons != null)
                        {
                            missive.Reasons = string.Join(",", requestDto.Reasons);
                        }
                        steamNotityText =
                            $"动态「{activitySummary}」中的评论「{commentSummary}」已被警告,若在 30 天之内收到两次警告,你的账户将被自动停权 14 天。";
                        break;
                    }
                }
                else
                {
                    switch (requestDto.Property)
                    {
                    case ActivityCommentUpdateOneModerationRequestDto.CommentProperty.Archived:
                        missive.Type    = MessageType.ActivityCommentArchiveCancel;
                        steamNotityText =
                            $"动态「{activitySummary}」下评论「{commentSummary}」的封存已被撤销,此则评论的内容和作者信息已重新公开。";
                        break;

                    case ActivityCommentUpdateOneModerationRequestDto.CommentProperty.Warned:
                        missive.Type    = MessageType.ActivityCommentWarningCancel;
                        steamNotityText =
                            $"动态「{activitySummary}」下评论「{commentSummary}」收到的警告已被撤销,之前的警告将不再纳入停权计数器的考量中,除非你的账户已经因收到警告而被自动停权。";
                        break;
                    }
                }
                await _cachedData.Messages.AddAsync(missive);

                // Steam 通知

                if (!string.IsNullOrWhiteSpace(steamNotityText))
                {
                    await _userManager.SendSteamChatMessageAsync(comment.Commentator, steamNotityText);
                }
            }
            return(Ok());
        }
Esempio n. 3
0
        public async Task <IHttpActionResult> CreateOne(string targetId, LikeTargetType targetType)
        {
            var operatorId = User.Identity.GetUserId();
            var @operator  = await _userManager.FindByIdAsync(operatorId);

            if (@operator.FreeLike <= 0 && !await _coupon.CanTriggerEventAsync(operatorId, CouponEvent.发出认可))
            {
                return(Unauthorized());
            }

            var likeId = await _cachedData.Likes.AddAsync(operatorId, targetId, targetType);

            var free = string.Empty;

            if (likeId != null)
            {
                if (targetType == LikeTargetType.Article || targetType == LikeTargetType.Activity)
                {
                    _mqChannel.SendMessage(string.Empty, MqClientProvider.PushHubRequestQueue, new PushHubRequestDto
                    {
                        Type      = ContentPushType.Like,
                        ContentId = likeId
                    });
                }

                KeylolUser  targetUser;
                bool        notify, steamNotify;
                MessageType messageType;
                string      steamNotifyText;
                object      couponDescriptionForTargetUser, couponDescriptionForOperator;
                switch (targetType)
                {
                case LikeTargetType.Article:
                    messageType = MessageType.ArticleLike;
                    var article = await _dbContext.Articles.Where(a => a.Id == targetId)
                                  .Select(a => new
                    {
                        a.Id,
                        a.Title,
                        a.Author,
                        a.SidForAuthor
                    }).SingleAsync();

                    targetUser      = article.Author;
                    notify          = targetUser.NotifyOnArticleLiked;
                    steamNotify     = targetUser.SteamNotifyOnArticleLiked;
                    steamNotifyText =
                        $"{@operator.UserName} 认可了你的文章《{article.Title}》:\nhttps://www.keylol.com/article/{targetUser.IdCode}/{article.SidForAuthor}";
                    couponDescriptionForTargetUser = new
                    {
                        ArticleId  = article.Id,
                        OperatorId = operatorId
                    };
                    couponDescriptionForOperator = new { ArticleId = article.Id };
                    break;

                case LikeTargetType.ArticleComment:
                    messageType = MessageType.ArticleCommentLike;
                    var articleComment = await _dbContext.ArticleComments.Where(c => c.Id == targetId)
                                         .Select(c => new
                    {
                        c.Id,
                        c.Commentator,
                        c.SidForArticle,
                        ArticleTitle        = c.Article.Title,
                        ArticleSidForAuthor = c.Article.SidForAuthor,
                        ArticleAuthorIdCode = c.Article.Author.IdCode
                    }).SingleAsync();

                    targetUser      = articleComment.Commentator;
                    notify          = targetUser.NotifyOnCommentLiked;
                    steamNotify     = targetUser.SteamNotifyOnCommentLiked;
                    steamNotifyText =
                        $"{@operator.UserName} 认可了你在《{articleComment.ArticleTitle}》下的评论:\nhttps://www.keylol.com/article/{articleComment.ArticleAuthorIdCode}/{articleComment.ArticleSidForAuthor}#{articleComment.SidForArticle}";
                    couponDescriptionForTargetUser = new
                    {
                        ArticleCommentId = articleComment.Id,
                        OperatorId       = operatorId
                    };
                    couponDescriptionForOperator = new { ArticleCommentId = articleComment.Id };
                    break;

                case LikeTargetType.Activity:
                    messageType = MessageType.ActivityLike;
                    var activity = await _dbContext.Activities.Include(a => a.Author)
                                   .Where(a => a.Id == targetId).SingleAsync();

                    targetUser      = activity.Author;
                    notify          = targetUser.NotifyOnActivityLiked;
                    steamNotify     = targetUser.SteamNotifyOnActivityLiked;
                    steamNotifyText =
                        $"{@operator.UserName} 认可了你的动态「{PostOfficeMessageList.CollapseActivityContent(activity)}」:\nhttps://www.keylol.com/activity/{targetUser.IdCode}/{activity.SidForAuthor}";
                    couponDescriptionForTargetUser = new
                    {
                        ActivityId = activity.Id,
                        OperatorId = operatorId
                    };
                    couponDescriptionForOperator = new { ActivityId = activity.Id };
                    break;

                case LikeTargetType.ActivityComment:
                    messageType = MessageType.ActivityCommentLike;
                    var activityComment = await _dbContext.ActivityComments.Where(c => c.Id == targetId)
                                          .Select(c => new
                    {
                        c.Id,
                        c.Commentator,
                        c.SidForActivity,
                        c.Activity,
                        ActivityAuthorIdCode = c.Activity.Author.IdCode
                    }).SingleAsync();

                    targetUser      = activityComment.Commentator;
                    notify          = targetUser.NotifyOnCommentLiked;
                    steamNotify     = targetUser.SteamNotifyOnCommentLiked;
                    steamNotifyText =
                        $"{@operator.UserName} 认可了你在「{PostOfficeMessageList.CollapseActivityContent(activityComment.Activity)}」下的评论:\nhttps://www.keylol.com/activity/{activityComment.ActivityAuthorIdCode}/{activityComment.Activity.SidForAuthor}#{activityComment.SidForActivity}";
                    couponDescriptionForTargetUser = new
                    {
                        ActivityCommentId = activityComment.Id,
                        OperatorId        = operatorId
                    };
                    couponDescriptionForOperator = new { ActivityCommentId = activityComment.Id };
                    break;

                default:
                    throw new ArgumentOutOfRangeException(nameof(targetType), targetType, null);
                }
                if (@operator.FreeLike > 0)
                {
                    @operator.FreeLike--;
                    free = "Free";
                }
                else
                {
                    await _coupon.UpdateAsync(@operator, CouponEvent.发出认可, couponDescriptionForOperator);
                }
                await _coupon.UpdateAsync(targetUser, CouponEvent.获得认可, couponDescriptionForTargetUser);

                if (notify)
                {
                    var message = new Message
                    {
                        Type        = messageType,
                        OperatorId  = operatorId,
                        ReceiverId  = targetUser.Id,
                        Count       = await _cachedData.Likes.GetUserLikeCountAsync(targetUser.Id),
                        SecondCount = await _cachedData.Likes.GetTargetLikeCountAsync(targetId, targetType)
                    };
                    switch (targetType)
                    {
                    case LikeTargetType.Article:
                        message.ArticleId = targetId;
                        break;

                    case LikeTargetType.ArticleComment:
                        message.ArticleCommentId = targetId;
                        break;

                    case LikeTargetType.Activity:
                        message.ActivityId = targetId;
                        break;

                    case LikeTargetType.ActivityComment:
                        message.ActivityCommentId = targetId;
                        break;

                    default:
                        throw new ArgumentOutOfRangeException(nameof(targetType), targetType, null);
                    }
                    await _cachedData.Messages.AddAsync(message);
                }
                if (steamNotify)
                {
                    await _userManager.SendSteamChatMessageAsync(targetUser, steamNotifyText);
                }
            }
            return(Ok(free));
        }
        public async Task <IHttpActionResult> UpdoteOneModeration(string id,
                                                                  [NotNull] ActivityUpdateOneModerationRequestDto requestDto)
        {
            var activity =
                await _dbContext.Activities.Include(a => a.Author).Where(a => a.Id == id).SingleOrDefaultAsync();

            if (activity == null)
            {
                return(NotFound());
            }

            var operatorId       = User.Identity.GetUserId();
            var isKeylolOperator = User.IsInRole(KeylolRoles.Operator);

            if (!isKeylolOperator)
            {
                switch (requestDto.Property)
                {
                case ActivityUpdateOneModerationRequestDto.ActivityProperty.Archived:
                    if (activity.AuthorId != operatorId)
                    {
                        return(Unauthorized());
                    }
                    break;

                default:
                    return(Unauthorized());
                }
            }

            if (!Enum.IsDefined(typeof(ActivityUpdateOneModerationRequestDto.ActivityProperty), requestDto.Property))
            {
                throw new ArgumentOutOfRangeException(nameof(requestDto.Property));
            }
            var propertyInfo = typeof(Models.Activity).GetProperty(requestDto.Property.ToString());

            if (requestDto.Property == ActivityUpdateOneModerationRequestDto.ActivityProperty.Archived)
            {
                if (activity.Archived != ArchivedState.None == requestDto.Value)
                {
                    return(this.BadRequest(nameof(requestDto), nameof(requestDto.Value), Errors.Duplicate));
                }

                if (isKeylolOperator)
                {
                    activity.Archived = requestDto.Value ? ArchivedState.Operator : ArchivedState.None;
                }
                else
                {
                    if (activity.Archived == ArchivedState.Operator)
                    {
                        return(Unauthorized());
                    }
                    activity.Archived = requestDto.Value ? ArchivedState.User : ArchivedState.None;
                }
            }
            else
            {
                if ((bool)propertyInfo.GetValue(activity) == requestDto.Value)
                {
                    return(this.BadRequest(nameof(requestDto), nameof(requestDto.Value), Errors.Duplicate));
                }

                propertyInfo.SetValue(activity, requestDto.Value);
            }
            await _dbContext.SaveChangesAsync();

            if (isKeylolOperator && (requestDto.NotifyAuthor ?? false))
            {
                var missive = new Message
                {
                    OperatorId = operatorId,
                    ReceiverId = activity.AuthorId,
                    ActivityId = activity.Id
                };
                string steamNotityText = null;
                var    activitySummary = PostOfficeMessageList.CollapseActivityContent(activity, 30);
                if (requestDto.Value)
                {
                    switch (requestDto.Property)
                    {
                    case ActivityUpdateOneModerationRequestDto.ActivityProperty.Archived:
                        missive.Type = MessageType.ActivityArchive;
                        if (requestDto.Reasons != null)
                        {
                            missive.Reasons = string.Join(",", requestDto.Reasons);
                        }
                        steamNotityText = $"动态「{activitySummary}」已被封存,封存后该动态的内容和所有评论会被隐藏,同时这则动态不会再显示于任何轨道上。";
                        break;

                    case ActivityUpdateOneModerationRequestDto.ActivityProperty.Rejected:
                        missive.Type = MessageType.ActivityRejection;
                        if (requestDto.Reasons != null)
                        {
                            missive.Reasons = string.Join(",", requestDto.Reasons);
                        }
                        steamNotityText = $"动态「{activitySummary}」已被退稿,不会再出现于其他用户或据点的轨道上,这则动态后续的投稿也将被自动回绝。";
                        break;

                    case ActivityUpdateOneModerationRequestDto.ActivityProperty.Warned:
                        missive.Type = MessageType.ActivityWarning;
                        if (requestDto.Reasons != null)
                        {
                            missive.Reasons = string.Join(",", requestDto.Reasons);
                        }
                        steamNotityText = $"动态「{activitySummary}」已被警告,若在 30 天之内收到两次警告,你的账户将被自动停权 14 天。";
                        break;
                    }
                }
                else
                {
                    switch (requestDto.Property)
                    {
                    case ActivityUpdateOneModerationRequestDto.ActivityProperty.Archived:
                        missive.Type    = MessageType.ActivityArchiveCancel;
                        steamNotityText = $"动态「{activitySummary}」的封存已被撤销,该动态的内容和所有评论已重新公开,轨道将不再隐藏这则动态。";
                        break;

                    case ActivityUpdateOneModerationRequestDto.ActivityProperty.Rejected:
                        missive.Type    = MessageType.ActivityRejectionCancel;
                        steamNotityText = $"动态「{activitySummary}」的退稿限制已被撤销,其他用户首页的轨道将不再隐藏这则动态,后续的投稿也不再会被其他据点回绝。";
                        break;

                    case ActivityUpdateOneModerationRequestDto.ActivityProperty.Warned:
                        missive.Type    = MessageType.ActivityWarningCancel;
                        steamNotityText = $"动态「{activitySummary}」的警告已被撤销,之前的警告将不再纳入停权计数器的考量中,除非你的账户已经因收到警告而被自动停权。";
                        break;
                    }
                }
                await _cachedData.Messages.AddAsync(missive);

                // Steam 通知

                if (!string.IsNullOrWhiteSpace(steamNotityText))
                {
                    await _userManager.SendSteamChatMessageAsync(activity.Author, steamNotityText);
                }
            }
            return(Ok());
        }