using Masuit.MyBlogs.Core.Common; using Masuit.MyBlogs.Core.Extensions; using Masuit.MyBlogs.Core.Infrastructure.Services.Interface; using Masuit.MyBlogs.Core.Models.Enum; using Masuit.MyBlogs.Core.Models.ViewModel; using Masuit.Tools; using Masuit.Tools.Core.Net; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Caching.Memory; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using WilderMinds.RssSyndication; using Z.EntityFramework.Plus; namespace Masuit.MyBlogs.Core.Controllers { /// /// 订阅服务 /// public class SubscribeController : Controller { /// /// 文章 /// public IPostService PostService { get; set; } public ICategoryService CategoryService { get; set; } public ICommentService CommentService { get; set; } public IAdvertisementService AdvertisementService { get; set; } /// /// RSS订阅 /// /// [Route("/rss"), ResponseCache(Duration = 3600)] public IActionResult Rss() { var time = DateTime.Today.AddDays(-1); string scheme = Request.Scheme; var host = Request.Host; var posts = PostService.GetQueryNoTracking(p => p.Status == Status.Published && p.ModifyDate >= time, p => p.ModifyDate, false).Select(p => new Item() { Author = new Author { Name = p.Author, Email = p.Email.MaskEmail('*') }, Body = p.Content.GetSummary(300, 50), Categories = new List { p.Category.Name }, Link = new Uri(scheme + "://" + host + "/" + p.Id), PublishDate = p.ModifyDate.ToTimeZone(HttpContext.Session.Get(SessionKey.TimeZone)), Title = p.Title, Permalink = scheme + "://" + host + "/" + p.Id, Guid = p.Id.ToString(), FullHtmlContent = p.Content.GetSummary(300, 50) }).FromCache(new MemoryCacheEntryOptions() { AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(1) }).ToList(); InsertAdvertisement(posts); var feed = new Feed() { Title = CommonHelper.SystemSettings["Title"], Description = CommonHelper.SystemSettings["Description"], Link = new Uri(scheme + "://" + host + "/rss"), Copyright = CommonHelper.SystemSettings["Title"], Language = "zh-cn", Items = posts.ToArray() }; var rss = feed.Serialize(new SerializeOption() { Encoding = Encoding.UTF8 }); return Content(rss, "text/xml"); } private void InsertAdvertisement(List posts, int? cid = null) { if (posts.Count > 2) { var ad = AdvertisementService.GetByWeightedPrice((AdvertiseType)(DateTime.Now.Second % 4 + 1), cid); if (ad is not null) { posts.Insert(new Random().Next(1, posts.Count), new Item() { Author = new Author() { Name = ad.IndexId }, Body = ad.Description, Title = ad.Title, FullHtmlContent = ad.Description, Guid = ad.IndexId, PublishDate = DateTime.UtcNow, Link = new Uri(Url.ActionLink("Redirect", "Advertisement", new { id = ad.Id })), Permalink = Url.ActionLink("Redirect", "Advertisement", new { id = ad.Id }) }); } } } /// /// RSS分类订阅 /// /// [Route("/cat/{id}/rss"), ResponseCache(Duration = 3600)] public async Task CategoryRss(int id) { var time = DateTime.Today.AddDays(-1); string scheme = Request.Scheme; var host = Request.Host; var category = await CategoryService.GetByIdAsync(id) ?? throw new NotFoundException("分类未找到"); var posts = PostService.GetQueryNoTracking(p => p.CategoryId == id && p.Status == Status.Published && p.ModifyDate >= time, p => p.ModifyDate, false).Select(p => new Item() { Author = new Author { Name = p.Author, Email = p.Email.MaskEmail('*') }, Body = p.Content.GetSummary(300, 50), Categories = new List { p.Category.Name }, Link = new Uri(scheme + "://" + host + "/" + p.Id), PublishDate = p.ModifyDate.ToTimeZone(HttpContext.Session.Get(SessionKey.TimeZone)), Title = p.Title, Permalink = scheme + "://" + host + "/" + p.Id, Guid = p.Id.ToString(), FullHtmlContent = p.Content.GetSummary(300, 50) }).FromCache(new MemoryCacheEntryOptions() { AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(1) }).ToList(); InsertAdvertisement(posts, id); var feed = new Feed() { Title = Request.Host + $":分类{category.Name}文章订阅", Description = category.Description, Link = new Uri(scheme + "://" + host + "/rss"), Copyright = CommonHelper.SystemSettings["Title"], Language = "zh-cn", Items = posts.ToArray() }; var rss = feed.Serialize(new SerializeOption() { Encoding = Encoding.UTF8 }); return Content(rss, "text/xml"); } /// /// RSS文章订阅 /// /// [Route("/{id}/rss"), ResponseCache(Duration = 3600)] public async Task PostRss(int id) { string scheme = Request.Scheme; var host = Request.Host; var p = await PostService.GetAsync(p => p.Status == Status.Published && p.Id == id) ?? throw new NotFoundException("文章未找到"); var summary = p.Content.GetSummary(300, 50); var item = new Item() { Author = new Author { Name = p.Author, Email = p.Email.MaskEmail() }, Body = summary, Categories = new List { p.Category.Name }, Link = new Uri(scheme + "://" + host + "/" + p.Id), PublishDate = p.ModifyDate.ToTimeZone(HttpContext.Session.Get(SessionKey.TimeZone)), Title = p.Title, Permalink = scheme + "://" + host + "/" + p.Id, Guid = p.Id.ToString(), FullHtmlContent = summary }; var feed = new Feed() { Title = Request.Host + $":文章【{p.Title}】更新订阅", Description = summary, Link = new Uri(scheme + "://" + host + "/rss/" + id), Copyright = CommonHelper.SystemSettings["Title"], Language = "zh-cn", Items = new List() { item } }; var rss = feed.Serialize(new SerializeOption() { Encoding = Encoding.UTF8 }); return Content(rss, "text/xml"); } /// /// RSS文章评论订阅 /// /// [Route("/{id}/comments/rss"), ResponseCache(Duration = 600)] public async Task CommentsRss(int id) { string scheme = Request.Scheme; var host = Request.Host; var post = await PostService.GetAsync(p => p.Status == Status.Published && p.Id == id) ?? throw new NotFoundException("文章不存在"); var start = DateTime.Today.AddDays(-7); var comments = await CommentService.GetQuery(c => c.PostId == post.Id && c.CommentDate > start).Select(c => new Item() { Author = new Author { Name = c.NickName }, Body = c.Content, Categories = new List { c.Post.Title }, Link = new Uri($"{scheme}://{host}/{post.Id}?cid={c.Id}#comment"), PublishDate = c.CommentDate.ToTimeZone(HttpContext.Session.Get(SessionKey.TimeZone)), Title = c.NickName, Permalink = $"{scheme}://{host}/{post.Id}?cid={c.Id}#comment", Guid = c.Id.ToString(), FullHtmlContent = c.Content }).FromCacheAsync(new MemoryCacheEntryOptions() { AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(10) }); var feed = new Feed() { Title = Request.Host + $":文章【{post.Title}】文章评论更新订阅", Description = post.Content.GetSummary(300, 50), Link = new Uri(scheme + "://" + host + "/rss/" + id + "/comments"), Copyright = CommonHelper.SystemSettings["Title"], Language = "zh-cn", Items = comments.ToArray() }; var rss = feed.Serialize(new SerializeOption() { Encoding = Encoding.UTF8 }); return Content(rss, "text/xml"); } } }