예제 #1
0
        private async Task UpdateMemoryPostsAsync()
        {
            var memPosts  = GetPosts();
            var filePosts = await GetPostsFromFileAsync();

            var posts = new List <BlogPost>();

            foreach (var filePost in filePosts)
            {
                if (StringEqualsHelper.IgnoreCase(filePost.GitHubPath, BlogConstant.TemplatePostGitHubPath))
                {
                    continue;
                }

                var memPost = memPosts.FirstOrDefault(p =>
                                                      StringEqualsHelper.IgnoreCase(p.Link, filePost.Link));
                if (memPost != null)
                {
                    filePost.Visits = Math.Max(filePost.Visits, memPost.Visits);
                }

                posts.Add(filePost);
            }

            _memoryCacheClient.Set(CacheKeyBuilder.Build(SiteComponent.Blog, "post", "all"), posts);
        }
예제 #2
0
        public IActionResult Index([FromQuery] int p)
        {
            var posts = User.Identity.IsAuthenticated?
                        _blogService.GetPosts(false, ref p, out var totalPages) :
                        _blogService.GetPosts(true, ref p, out totalPages);

            // very ugly
            var putAtTopPosts = posts.Where(_ => _.PutAtTop).OrderByDescending(_ => _.CreationTimeUtc).ToList();

            foreach (var post in putAtTopPosts)
            {
                posts.Remove(post);
            }

            posts.InsertRange(0, putAtTopPosts);

            var categories     = _blogService.GetCategories();
            var tags           = _blogService.GetTags();
            var postViewModels = new List <PostViewModel>();

            foreach (var blogPost in posts)
            {
                var postViewModel = new PostViewModel(blogPost);
                foreach (var blogPostCategoryName in blogPost.CategoryNames)
                {
                    var cat = categories.FirstOrDefault(_ =>
                                                        StringEqualsHelper.IgnoreCase(_.Name, blogPostCategoryName));
                    if (cat != null)
                    {
                        postViewModel.Categories.Add(cat);
                    }
                }

                foreach (var blogPostTagName in blogPost.TagNames)
                {
                    var tag = tags.FirstOrDefault(_ =>
                                                  StringEqualsHelper.IgnoreCase(_.Name, blogPostTagName));
                    if (tag != null)
                    {
                        postViewModel.Tags.Add(tag);
                    }
                }

                postViewModels.Add(postViewModel);
            }

            if (p > 1)
            {
                ViewData["Title"]  = $"第{p}页";
                ViewData["Robots"] = "noindex, nofollow";
            }

            ViewData["Canonical"] = "/";
            return(View(new PagedPostViewModel {
                CurrentPage = p, TotalPages = totalPages, Posts = postViewModels, Url = Request.Path
            }));
        }
예제 #3
0
        public BlogPost GetPost(int year, int month, string link)
        {
            var posts = GetPosts();
            var post  = posts.FirstOrDefault(p =>
                                             p.CreationTimeUtc.Year == year &&
                                             p.CreationTimeUtc.Month == month &&
                                             StringEqualsHelper.IgnoreCase(p.Link, link));

            post?.AddVisit();

            return(post);
        }
예제 #4
0
        public async Task <IViewComponentResult> InvokeAsync(bool adminView, string excludedLink)
        {
            List <BlogPost> posts;

            if (adminView)
            {
                posts = _blogService.GetPosts()
                        .Where(p => p.IsReallyPublic)
                        .ToList();
            }
            else
            {
                posts = _blogService.GetPosts().ToList();
            }

            var post            = posts.FirstOrDefault(p => StringEqualsHelper.IgnoreCase(excludedLink, p.Link));
            var postsWithWeight = new List <PostWithWeight>();
            var latestPost      = posts.OrderByDescending(p => p.CreationTimeUtc).FirstOrDefault();

            foreach (var blogPost in posts)
            {
                if (blogPost == post)
                {
                    continue;
                }

                var postWithWeight = new PostWithWeight {
                    Post = blogPost
                };
                if (post == null)
                {
                    if (latestPost != null)
                    {
                        postWithWeight.TicksDiff = (blogPost.CreationTimeUtc - latestPost.CreationTimeUtc).Ticks;
                    }
                }
                else
                {
                    if (blogPost.CategoryNames.Any(c => post.CategoryNames.Contains(c)))
                    {
                        postWithWeight.Weight += 0.7;
                    }

                    if (blogPost.TagNames.Any(t => post.TagNames.Contains(t)))
                    {
                        postWithWeight.Weight += 0.9;
                    }
                }

                postsWithWeight.Add(postWithWeight);
            }

            double totalVisits    = 1.0;
            double totalTicksDiff = 1.0;

            foreach (var postWithWeight in postsWithWeight)
            {
                totalVisits    += postWithWeight.Post.Visits;
                totalTicksDiff += postWithWeight.TicksDiff;
            }

            foreach (var postWithWeight in postsWithWeight)
            {
                postWithWeight.Weight -= postWithWeight.Post.Visits / (double)totalVisits;
                postWithWeight.Weight += postWithWeight.TicksDiff / totalTicksDiff;
            }

            return(View(postsWithWeight.OrderByDescending(pw => pw.Weight).Take(8).Select(pw => pw.Post)));
        }
예제 #5
0
        public IActionResult Index(int year, int month, string url)
        {
            var post = _blogService.GetPost(year, month, url);

            if (post == null)
            {
                _logger.LogWarning("Request post not exists. {Year}, {Month}, {Link}", year, month, url);
                return(NotFound());
            }

            if (!post.IsReallyPublic)
            {
                ViewData["Robots"] = "noindex, nofollow";

                if (!User.Identity.IsAuthenticated)
                {
                    _logger.LogWarning("Trying to access private post failed. {Year}, {Month}, {Link}", year, month, url);
                    return(NotFound());
                }
            }



            var categories    = _blogService.GetCategories();
            var tags          = _blogService.GetTags();
            var postViewModel = new PostViewModel(post);

            foreach (var blogPostCategoryName in post.CategoryNames)
            {
                var cat = categories.FirstOrDefault(_ =>
                                                    StringEqualsHelper.IgnoreCase(_.Name, blogPostCategoryName));
                if (cat != null)
                {
                    postViewModel.Categories.Add(cat);
                }
            }

            foreach (var blogPostTagName in post.TagNames)
            {
                var tag = tags.FirstOrDefault(_ =>
                                              StringEqualsHelper.IgnoreCase(_.Name, blogPostTagName));
                if (tag != null)
                {
                    postViewModel.Tags.Add(tag);
                }
            }

            var posts = User.Identity.IsAuthenticated
                ? _blogService.GetPosts().OrderByDescending(p => p.CreationTimeUtc).ToList()
                : _blogService.GetPosts().Where(p => p.IsReallyPublic).OrderByDescending(p => p.CreationTimeUtc).ToList();
            var postIndex = posts.IndexOf(post);

            if (postIndex > 0)
            {
                postViewModel.NextPost = posts[postIndex - 1];
            }

            if (postIndex < posts.Count - 1)
            {
                postViewModel.PrevPost = posts[postIndex + 1];
            }

            ViewData["Canonical"]   = post.FullUrlWithBaseAddress;
            ViewData["Title"]       = post.Title;
            ViewData["Description"] = post.ExcerptText;
            ViewData["AdminView"]   = HttpContext.User.Identity.IsAuthenticated;

            return(View(postViewModel));
        }
예제 #6
0
        public async Task <IActionResult> Hook()
        {
            if (!Request.Headers.ContainsKey("X-GitHub-Event") ||
                !Request.Headers.ContainsKey("X-Hub-Signature") ||
                !Request.Headers.ContainsKey("X-GitHub-Delivery"))
            {
                _logger.LogWarning("Headers are not completed.");
                return(BadRequest("Invalid Request."));
            }

            if (!StringEqualsHelper.IgnoreCase("push", Request.Headers["X-GitHub-Event"]))
            {
                _logger.LogWarning("Invalid github event {Event}", Request.Headers["X-GitHub-Event"]);
                return(BadRequest("Only support push event."));
            }

            var signature = Request.Headers["X-Hub-Signature"].ToString();

            if (!signature.StartsWith("sha1=", StringComparison.OrdinalIgnoreCase))
            {
                _logger.LogWarning("Invalid github signature {Signature}", signature);
                return(BadRequest("Invalid signature."));
            }

            using (var reader = new StreamReader(Request.Body))
            {
                var body = await reader.ReadToEndAsync();

                signature = signature.Substring("sha1=".Length);
                var secret    = Encoding.UTF8.GetBytes(_appConfig.AssetGitHubHookSecret);
                var bodyBytes = Encoding.UTF8.GetBytes(body);

                using (var hmacSha1 = new HMACSHA1(secret))
                {
                    var hash    = hmacSha1.ComputeHash(bodyBytes);
                    var builder = new StringBuilder(hash.Length * 2);
                    foreach (var b in hash)
                    {
                        builder.AppendFormat("{0:x2}", b);
                    }

                    var hashStr = builder.ToString();

                    if (!hashStr.Equals(signature))
                    {
                        _logger.LogWarning("Invalid github signature {Signature}, {HashString}", signature, hashStr);
                        return(BadRequest("Invalid signature."));
                    }
                }

                var payload = SerializeHelper.FromJson <GitHubPayload>(body);
                if (payload.Commits.Any(c =>
                                        StringEqualsHelper.IgnoreCase(_appConfig.AssetGitCommitEmail, c.Author.Email) &&
                                        StringEqualsHelper.IgnoreCase(_appConfig.AssetGitCommitUser, c.Author.User)))
                {
                    _logger.LogInformation("Got request from server, no need to refresh.");
                    return(Ok("No need to refresh."));
                }

                var modifiedPosts = payload.Commits.SelectMany(c => c.Modified).Distinct().ToList();
                await _blogService.UpdateMemoryAssetsAsync();

                _logger.LogInformation("Local assets refreshed.");

                if (modifiedPosts.Any())
                {
                    var posts = _blogService.GetPosts();
                    foreach (var blogPost in posts)
                    {
                        var modifiedPost = modifiedPosts.FirstOrDefault(p =>
                                                                        string.Equals(p, blogPost.GitHubPath, StringComparison.OrdinalIgnoreCase));
                        if (modifiedPost != null)
                        {
                            blogPost.LastUpdateTimeUtc = DateTime.UtcNow;
                        }
                    }
                }

                await _blogService.UpdateCloudAssetsAsync();

                _logger.LogInformation("Cloud assets updated.");

                var email = new StringBuilder();
                email.AppendLine($"<h3>ADDED POSTS</h3><ul>");
                foreach (var post in payload.Commits.SelectMany(c => c.Added).Distinct())
                {
                    email.AppendLine($"<li>{post}</li>");
                }

                email.AppendLine("</ul><h3>MODIFIED POSTS</h3><ul>");
                foreach (var post in modifiedPosts)
                {
                    email.AppendLine($"<li>{post}</li>");
                }

                email.AppendLine("</ul>");

                await _emailClient.SendAsync(
                    BlogConstant.LogSenderName,
                    BlogConstant.LogSenderEmail,
                    BlogConstant.AuthorEnglishName,
                    BlogConstant.AuthorEmail,
                    "GITHUB HOOK COMPLETED",
                    $"<p>GitHub hook executed completed.</p>{email}");

                return(Ok("Local updated."));
            }
        }