SubscribeController.cs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. using Masuit.MyBlogs.Core.Common;
  2. using Masuit.MyBlogs.Core.Extensions;
  3. using Masuit.MyBlogs.Core.Infrastructure.Services.Interface;
  4. using Masuit.MyBlogs.Core.Models.Enum;
  5. using Masuit.MyBlogs.Core.Models.ViewModel;
  6. using Masuit.Tools;
  7. using Masuit.Tools.Core.Net;
  8. using Microsoft.AspNetCore.Mvc;
  9. using Microsoft.Extensions.Caching.Memory;
  10. using System;
  11. using System.Collections.Generic;
  12. using System.Linq;
  13. using System.Text;
  14. using System.Threading.Tasks;
  15. using WilderMinds.RssSyndication;
  16. using Z.EntityFramework.Plus;
  17. namespace Masuit.MyBlogs.Core.Controllers
  18. {
  19. /// <summary>
  20. /// 订阅服务
  21. /// </summary>
  22. public class SubscribeController : Controller
  23. {
  24. /// <summary>
  25. /// 文章
  26. /// </summary>
  27. public IPostService PostService { get; set; }
  28. public ICategoryService CategoryService { get; set; }
  29. public ICommentService CommentService { get; set; }
  30. public IAdvertisementService AdvertisementService { get; set; }
  31. /// <summary>
  32. /// RSS订阅
  33. /// </summary>
  34. /// <returns></returns>
  35. [Route("/rss"), ResponseCache(Duration = 3600)]
  36. public IActionResult Rss()
  37. {
  38. var time = DateTime.Today.AddDays(-1);
  39. string scheme = Request.Scheme;
  40. var host = Request.Host;
  41. var posts = PostService.GetQueryNoTracking(p => p.Status == Status.Published && p.ModifyDate >= time, p => p.ModifyDate, false).Select(p => new Item()
  42. {
  43. Author = new Author
  44. {
  45. Name = p.Author,
  46. Email = p.Email.MaskEmail('*')
  47. },
  48. Body = p.Content.GetSummary(300, 50),
  49. Categories = new List<string>
  50. {
  51. p.Category.Name
  52. },
  53. Link = new Uri(scheme + "://" + host + "/" + p.Id),
  54. PublishDate = p.ModifyDate.ToTimeZone(HttpContext.Session.Get<string>(SessionKey.TimeZone)),
  55. Title = p.Title,
  56. Permalink = scheme + "://" + host + "/" + p.Id,
  57. Guid = p.Id.ToString(),
  58. FullHtmlContent = p.Content.GetSummary(300, 50)
  59. }).FromCache(new MemoryCacheEntryOptions()
  60. {
  61. AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(1)
  62. }).ToList();
  63. InsertAdvertisement(posts);
  64. var feed = new Feed()
  65. {
  66. Title = CommonHelper.SystemSettings["Title"],
  67. Description = CommonHelper.SystemSettings["Description"],
  68. Link = new Uri(scheme + "://" + host + "/rss"),
  69. Copyright = CommonHelper.SystemSettings["Title"],
  70. Language = "zh-cn",
  71. Items = posts.ToArray()
  72. };
  73. var rss = feed.Serialize(new SerializeOption()
  74. {
  75. Encoding = Encoding.UTF8
  76. });
  77. return Content(rss, "text/xml");
  78. }
  79. private void InsertAdvertisement(List<Item> posts, int? cid = null)
  80. {
  81. if (posts.Count > 2)
  82. {
  83. var ad = AdvertisementService.GetByWeightedPrice((AdvertiseType)(DateTime.Now.Second % 4 + 1), cid);
  84. if (ad is not null)
  85. {
  86. posts.Insert(new Random().Next(1, posts.Count), new Item()
  87. {
  88. Author = new Author()
  89. {
  90. Name = ad.IndexId
  91. },
  92. Body = ad.Description,
  93. Title = ad.Title,
  94. FullHtmlContent = ad.Description,
  95. Guid = ad.IndexId,
  96. PublishDate = DateTime.UtcNow,
  97. Link = new Uri(Url.ActionLink("Redirect", "Advertisement", new { id = ad.Id })),
  98. Permalink = Url.ActionLink("Redirect", "Advertisement", new { id = ad.Id })
  99. });
  100. }
  101. }
  102. }
  103. /// <summary>
  104. /// RSS分类订阅
  105. /// </summary>
  106. /// <returns></returns>
  107. [Route("/cat/{id}/rss"), ResponseCache(Duration = 3600)]
  108. public async Task<IActionResult> CategoryRss(int id)
  109. {
  110. var time = DateTime.Today.AddDays(-1);
  111. string scheme = Request.Scheme;
  112. var host = Request.Host;
  113. var category = await CategoryService.GetByIdAsync(id) ?? throw new NotFoundException("分类未找到");
  114. var posts = PostService.GetQueryNoTracking(p => p.CategoryId == id && p.Status == Status.Published && p.ModifyDate >= time, p => p.ModifyDate, false).Select(p => new Item()
  115. {
  116. Author = new Author
  117. {
  118. Name = p.Author,
  119. Email = p.Email.MaskEmail('*')
  120. },
  121. Body = p.Content.GetSummary(300, 50),
  122. Categories = new List<string>
  123. {
  124. p.Category.Name
  125. },
  126. Link = new Uri(scheme + "://" + host + "/" + p.Id),
  127. PublishDate = p.ModifyDate.ToTimeZone(HttpContext.Session.Get<string>(SessionKey.TimeZone)),
  128. Title = p.Title,
  129. Permalink = scheme + "://" + host + "/" + p.Id,
  130. Guid = p.Id.ToString(),
  131. FullHtmlContent = p.Content.GetSummary(300, 50)
  132. }).FromCache(new MemoryCacheEntryOptions()
  133. {
  134. AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(1)
  135. }).ToList();
  136. InsertAdvertisement(posts, id);
  137. var feed = new Feed()
  138. {
  139. Title = Request.Host + $":分类{category.Name}文章订阅",
  140. Description = category.Description,
  141. Link = new Uri(scheme + "://" + host + "/rss"),
  142. Copyright = CommonHelper.SystemSettings["Title"],
  143. Language = "zh-cn",
  144. Items = posts.ToArray()
  145. };
  146. var rss = feed.Serialize(new SerializeOption()
  147. {
  148. Encoding = Encoding.UTF8
  149. });
  150. return Content(rss, "text/xml");
  151. }
  152. /// <summary>
  153. /// RSS文章订阅
  154. /// </summary>
  155. /// <returns></returns>
  156. [Route("/{id}/rss"), ResponseCache(Duration = 3600)]
  157. public async Task<IActionResult> PostRss(int id)
  158. {
  159. string scheme = Request.Scheme;
  160. var host = Request.Host;
  161. var p = await PostService.GetAsync(p => p.Status == Status.Published && p.Id == id) ?? throw new NotFoundException("文章未找到");
  162. var summary = p.Content.GetSummary(300, 50);
  163. var item = new Item()
  164. {
  165. Author = new Author
  166. {
  167. Name = p.Author,
  168. Email = p.Email.MaskEmail()
  169. },
  170. Body = summary,
  171. Categories = new List<string>
  172. {
  173. p.Category.Name
  174. },
  175. Link = new Uri(scheme + "://" + host + "/" + p.Id),
  176. PublishDate = p.ModifyDate.ToTimeZone(HttpContext.Session.Get<string>(SessionKey.TimeZone)),
  177. Title = p.Title,
  178. Permalink = scheme + "://" + host + "/" + p.Id,
  179. Guid = p.Id.ToString(),
  180. FullHtmlContent = summary
  181. };
  182. var feed = new Feed()
  183. {
  184. Title = Request.Host + $":文章【{p.Title}】更新订阅",
  185. Description = summary,
  186. Link = new Uri(scheme + "://" + host + "/rss/" + id),
  187. Copyright = CommonHelper.SystemSettings["Title"],
  188. Language = "zh-cn",
  189. Items = new List<Item>() { item }
  190. };
  191. var rss = feed.Serialize(new SerializeOption()
  192. {
  193. Encoding = Encoding.UTF8
  194. });
  195. return Content(rss, "text/xml");
  196. }
  197. /// <summary>
  198. /// RSS文章评论订阅
  199. /// </summary>
  200. /// <returns></returns>
  201. [Route("/{id}/comments/rss"), ResponseCache(Duration = 600)]
  202. public async Task<IActionResult> CommentsRss(int id)
  203. {
  204. string scheme = Request.Scheme;
  205. var host = Request.Host;
  206. var post = await PostService.GetAsync(p => p.Status == Status.Published && p.Id == id) ?? throw new NotFoundException("文章不存在");
  207. var start = DateTime.Today.AddDays(-7);
  208. var comments = await CommentService.GetQuery(c => c.PostId == post.Id && c.CommentDate > start).Select(c => new Item()
  209. {
  210. Author = new Author
  211. {
  212. Name = c.NickName
  213. },
  214. Body = c.Content,
  215. Categories = new List<string>
  216. {
  217. c.Post.Title
  218. },
  219. Link = new Uri($"{scheme}://{host}/{post.Id}?cid={c.Id}#comment"),
  220. PublishDate = c.CommentDate.ToTimeZone(HttpContext.Session.Get<string>(SessionKey.TimeZone)),
  221. Title = c.NickName,
  222. Permalink = $"{scheme}://{host}/{post.Id}?cid={c.Id}#comment",
  223. Guid = c.Id.ToString(),
  224. FullHtmlContent = c.Content
  225. }).FromCacheAsync(new MemoryCacheEntryOptions()
  226. {
  227. AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(10)
  228. });
  229. var feed = new Feed()
  230. {
  231. Title = Request.Host + $":文章【{post.Title}】文章评论更新订阅",
  232. Description = post.Content.GetSummary(300, 50),
  233. Link = new Uri(scheme + "://" + host + "/rss/" + id + "/comments"),
  234. Copyright = CommonHelper.SystemSettings["Title"],
  235. Language = "zh-cn",
  236. Items = comments.ToArray()
  237. };
  238. var rss = feed.Serialize(new SerializeOption()
  239. {
  240. Encoding = Encoding.UTF8
  241. });
  242. return Content(rss, "text/xml");
  243. }
  244. }
  245. }