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); }
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 })); }
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); }
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))); }
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)); }
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.")); } }