Beispiel #1
0
        /// <summary>
        /// 创建 <see cref="ArticlePage"/>
        /// </summary>
        /// <param name="authorIdCode">作者识别码</param>
        /// <param name="sidForAuthor">文章在作者名下的序号</param>
        /// <param name="currentUserId">当前登录用户 ID</param>
        /// <param name="isOperator">当前登录用户是否为运维职员</param>
        /// <param name="dbContext"><see cref="KeylolDbContext"/></param>
        /// <param name="cachedData"><see cref="CachedDataProvider"/></param>
        /// <param name="userManager"><see cref="KeylolUserManager"/></param>
        /// <returns><see cref="ArticlePage"/></returns>
        public static async Task <ArticlePage> CreateAsync(string authorIdCode, int sidForAuthor, string currentUserId,
                                                           bool isOperator, KeylolDbContext dbContext, CachedDataProvider cachedData, KeylolUserManager userManager)
        {
            var articlePage = new ArticlePage();

            var article = await dbContext.Articles
                          .Include(a => a.Author)
                          .Include(a => a.TargetPoint)
                          .Where(a => a.Author.IdCode == authorIdCode && a.SidForAuthor == sidForAuthor)
                          .SingleOrDefaultAsync();

            if (article == null)
            {
                return(articlePage);
            }

            articlePage.Archived = article.Archived != ArchivedState.None;
            if (articlePage.Archived.Value && currentUserId != article.AuthorId && !isOperator)
            {
                return(articlePage);
            }

            articlePage.PointBasicInfo =
                await PointBasicInfo.CreateAsync(currentUserId, article.TargetPoint, dbContext, cachedData);

            articlePage.AuthorBasicInfo = new UserBasicInfo
            {
                Id                  = article.Author.Id,
                IdCode              = article.Author.IdCode,
                AvatarImage         = article.Author.AvatarImage,
                UserName            = article.Author.UserName,
                FriendCount         = await cachedData.Subscriptions.GetFriendCountAsync(article.AuthorId),
                SubscribedUserCount = await cachedData.Subscriptions
                                      .GetSubscribedUserCountAsync(article.AuthorId),
                SubscriberCount = await cachedData.Subscriptions
                                  .GetSubscriberCountAsync(article.AuthorId, SubscriptionTargetType.User),
                IsFriend = string.IsNullOrWhiteSpace(currentUserId)
                    ? (bool?)null
                    : await cachedData.Users.IsFriendAsync(currentUserId, article.AuthorId),
                Subscribed = string.IsNullOrWhiteSpace(currentUserId)
                    ? (bool?)null
                    : await cachedData.Subscriptions.IsSubscribedAsync(currentUserId, article.AuthorId,
                                                                       SubscriptionTargetType.User),
                SteamId = await userManager.GetSteamIdAsync(article.AuthorId)
            };
            if (!string.IsNullOrWhiteSpace(articlePage.AuthorBasicInfo.SteamId))
            {
                articlePage.AuthorBasicInfo.SteamProfileName = article.Author.SteamProfileName;
            }
            articlePage.AuthorPlayedTime = article.TargetPoint.SteamAppId == null
                ? null
                : (await dbContext.UserSteamGameRecords
                   .Where(r => r.UserId == article.AuthorId && r.SteamAppId == article.TargetPoint.SteamAppId)
                   .SingleOrDefaultAsync())?.TotalPlayedTime;
            articlePage.Id       = article.Id;
            articlePage.Title    = article.Title;
            articlePage.Subtitle = article.Subtitle;
            var attachedPointIds = Helpers.SafeDeserialize <List <string> >(article.AttachedPoints) ?? new List <string>();

            articlePage.AttachedPoints = (from id in attachedPointIds
                                          join point in await(from point in dbContext.Points
                                                              where attachedPointIds.Contains(point.Id)
                                                              select new
            {
                point.Type,
                point.Id,
                point.IdCode,
                point.AvatarImage,
                point.ChineseName,
                point.EnglishName
            }).ToListAsync() on id equals point.Id
                                          select new PointBasicInfo
            {
                Type = point.Type,
                Id = point.Id,
                IdCode = point.IdCode,
                AvatarImage = point.AvatarImage,
                ChineseName = point.ChineseName,
                EnglishName = point.EnglishName
            }).ToList();
            articlePage.PublishTime             = article.PublishTime;
            articlePage.Rejected                = article.Rejected;
            articlePage.Spotlighted             = article.Spotlighted;
            articlePage.Warned                  = article.Warned;
            articlePage.Content                 = article.Content;
            articlePage.ReproductionRequirement =
                Helpers.SafeDeserialize <ReproductionRequirement>(article.ReproductionRequirement);
            articlePage.LikeCount = await cachedData.Likes.GetTargetLikeCountAsync(article.Id, LikeTargetType.Article);

            articlePage.Liked = string.IsNullOrWhiteSpace(currentUserId)
                ? (bool?)null
                : await cachedData.Likes.IsLikedAsync(currentUserId, article.Id, LikeTargetType.Article);

            articlePage.Rating              = article.Rating;
            articlePage.CoverImage          = article.CoverImage;
            articlePage.Pros                = Helpers.SafeDeserialize <List <string> >(article.Pros);
            articlePage.Cons                = Helpers.SafeDeserialize <List <string> >(article.Cons);
            articlePage.RecommendedArticles =
                await RecommendedArticleList.CreateAsync(article.Id, article.AuthorId, article.TargetPointId, dbContext);

            var comments = await ArticleCommentList.CreateAsync(article, 1, currentUserId, isOperator, true, dbContext,
                                                                cachedData);

            articlePage.CommentCount      = comments.Item2;
            articlePage.LatestCommentTime = comments.Item3;
            articlePage.CommentPageCount  = comments.Item4;
            articlePage.Comments          = comments.Item1;
            return(articlePage);
        }
        /// <summary>
        /// 创建 <see cref="ArticleCommentList"/>
        /// </summary>
        /// <param name="article">文章对象</param>
        /// <param name="page">分页页码</param>
        /// <param name="currentUserId">当前登录用户 ID</param>
        /// <param name="isOperator">当前登录用户是否为运维职员</param>
        /// <param name="returnMeta">是否返回元数据(总页数、总评论数、最新评论时间)</param>
        /// <param name="dbContext"><see cref="KeylolDbContext"/></param>
        /// <param name="cachedData"><see cref="CachedDataProvider"/></param>
        /// <returns>Item1 表示 <see cref="ArticleCommentList"/>, Item2 表示总评论数,Item3 表示最新评论时间,Item4 表示总页数</returns>
        public static async Task <Tuple <ArticleCommentList, int, DateTime?, int> > CreateAsync(Models.Article article,
                                                                                                int page, string currentUserId, bool isOperator, bool returnMeta, KeylolDbContext dbContext,
                                                                                                CachedDataProvider cachedData)
        {
            if (article.Archived != ArchivedState.None && currentUserId != article.AuthorId && !isOperator)
            {
                return(new Tuple <ArticleCommentList, int, DateTime?, int>(new ArticleCommentList(0), 0, null, 0));
            }

            var queryResult = await(from comment in dbContext.ArticleComments
                                    where comment.ArticleId == article.Id
                                    orderby comment.Sid
                                    select new
            {
                Author = comment.Commentator,
                comment.Id,
                comment.PublishTime,
                comment.SidForArticle,
                comment.Content,
                comment.ReplyToComment,
                ReplyToCommentAuthor = comment.ReplyToComment.Commentator,
                comment.Archived,
                comment.Warned
            }).TakePage(page, RecordsPerPage).ToListAsync();

            var result = new ArticleCommentList(queryResult.Count);

            foreach (var c in queryResult)
            {
                var articleComment = new ArticleComment
                {
                    Id            = c.Id,
                    SidForArticle = c.SidForArticle,
                    Archived      = c.Archived != ArchivedState.None
                };
                // ReSharper disable once PossibleInvalidOperationException
                if (!articleComment.Archived.Value || currentUserId == c.Author.Id || isOperator)
                {
                    articleComment.AuthorIdCode      = c.Author.IdCode;
                    articleComment.AuthorAvatarImage = c.Author.AvatarImage;
                    articleComment.AuthorUserName    = c.Author.UserName;
                    articleComment.AuthorPlayedTime  = article.TargetPoint.SteamAppId == null
                        ? null
                        : (await dbContext.UserSteamGameRecords
                           .Where(r => r.UserId == c.Author.Id && r.SteamAppId == article.TargetPoint.SteamAppId)
                           .SingleOrDefaultAsync())?.TotalPlayedTime;
                    articleComment.LikeCount =
                        await cachedData.Likes.GetTargetLikeCountAsync(c.Id, LikeTargetType.ArticleComment);

                    articleComment.Liked = string.IsNullOrWhiteSpace(currentUserId)
                        ? (bool?)null
                        : await cachedData.Likes.IsLikedAsync(currentUserId, c.Id, LikeTargetType.ArticleComment);

                    articleComment.PublishTime = c.PublishTime;
                    articleComment.Content     = c.Content;
                    if (c.ReplyToComment != null)
                    {
                        articleComment.ReplyToComment = new ArticleComment
                        {
                            SidForArticle     = c.ReplyToComment.SidForArticle,
                            AuthorAvatarImage = c.ReplyToCommentAuthor.AvatarImage,
                            AuthorUserName    = c.ReplyToCommentAuthor.UserName,
                            AuthorIdCode      = c.ReplyToCommentAuthor.IdCode,
                            Content           = c.ReplyToComment.UnstyledContent.Length > 150
                                ? c.ReplyToComment.UnstyledContent.Substring(0, 150)
                                : c.ReplyToComment.UnstyledContent
                        };
                    }
                    articleComment.Warned = c.Warned;
                }
                result.Add(articleComment);
            }
            var latestCommentTime = returnMeta
                ? await(from comment in dbContext.ArticleComments
                        where comment.ArticleId == article.Id
                        orderby comment.Sid descending
                        select comment.PublishTime).FirstOrDefaultAsync()
                : default(DateTime);
            var count = await cachedData.ArticleComments.GetArticleCommentCountAsync(article.Id);

            return(new Tuple <ArticleCommentList, int, DateTime?, int>(result,
                                                                       count,
                                                                       latestCommentTime == default(DateTime) ? (DateTime?)null : latestCommentTime,
                                                                       count > 0 ? (int)Math.Ceiling(count / (double)RecordsPerPage) : 1));
        }