/// <summary> /// 创建 <see cref="CommentPage"/> /// </summary> /// <param name="currentUserId">当前登录用户 ID</param> /// <param name="dbContext"><see cref="KeylolDbContext"/></param> /// <param name="cachedData"><see cref="CachedDataProvider"/></param> /// <returns><see cref="CommentPage"/></returns> public static async Task <CommentPage> CreateAsync(string currentUserId, KeylolDbContext dbContext, CachedDataProvider cachedData) { var messages = await PostOfficeMessageList.CreateAsync(typeof(CommentPage), currentUserId, 1, true, dbContext, cachedData); return(new CommentPage { MessagePageCount = messages.Item2, Messages = messages.Item1 }); }
/// <summary> /// 获取评论消息列表 /// </summary> /// <param name="page">分页页码</param> /// <param name="dbContext"><see cref="KeylolDbContext"/></param> /// <param name="cachedData"><see cref="CachedDataProvider"/></param> /// <returns><see cref="PostOfficeMessageList"/></returns> public static async Task <PostOfficeMessageList> GetMessages(int page, [Injected] KeylolDbContext dbContext, [Injected] CachedDataProvider cachedData) { return((await PostOfficeMessageList.CreateAsync(typeof(CommentPage), StateTreeHelper.GetCurrentUserId(), page, false, dbContext, cachedData)).Item1); }
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> 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] 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()); }
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()); }