CommentController.cs 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326
  1. using Hangfire;
  2. using Masuit.MyBlogs.Core.Common;
  3. using Masuit.MyBlogs.Core.Extensions;
  4. using Masuit.MyBlogs.Core.Infrastructure.Services.Interface;
  5. using Masuit.MyBlogs.Core.Models.DTO;
  6. using Masuit.MyBlogs.Core.Models.Entity;
  7. using Masuit.MyBlogs.Core.Models.Enum;
  8. using Masuit.MyBlogs.Core.Models.ViewModel;
  9. using Masuit.Tools.Core.Net;
  10. using Masuit.Tools.Html;
  11. using Microsoft.AspNetCore.Hosting;
  12. using Microsoft.AspNetCore.Http;
  13. using Microsoft.AspNetCore.Mvc;
  14. using Microsoft.Net.Http.Headers;
  15. using System;
  16. using System.Collections.Generic;
  17. using System.IO;
  18. using System.Linq;
  19. using System.Text.RegularExpressions;
  20. namespace Masuit.MyBlogs.Core.Controllers
  21. {
  22. /// <summary>
  23. /// 评论管理
  24. /// </summary>
  25. public class CommentController : BaseController
  26. {
  27. private ICommentService CommentService { get; }
  28. private IPostService PostService { get; }
  29. private IInternalMessageService MessageService { get; }
  30. private readonly IHostingEnvironment _hostingEnvironment;
  31. /// <summary>
  32. /// 评论管理
  33. /// </summary>
  34. /// <param name="commentService"></param>
  35. /// <param name="postService"></param>
  36. /// <param name="messageService"></param>
  37. /// <param name="hostingEnvironment"></param>
  38. public CommentController(ICommentService commentService, IPostService postService, IInternalMessageService messageService, IHostingEnvironment hostingEnvironment)
  39. {
  40. CommentService = commentService;
  41. PostService = postService;
  42. MessageService = messageService;
  43. _hostingEnvironment = hostingEnvironment;
  44. }
  45. /// <summary>
  46. /// 发表评论
  47. /// </summary>
  48. /// <param name="comment"></param>
  49. /// <returns></returns>
  50. [HttpPost, ValidateAntiForgeryToken]
  51. public ActionResult Put(CommentInputDto comment)
  52. {
  53. if (Regex.Match(comment.Content, CommonHelper.BanRegex).Length > 0)
  54. {
  55. return ResultData(null, false, "您提交的内容包含敏感词,被禁止发表,请注意改善您的言辞!");
  56. }
  57. Post post = PostService.GetById(comment.PostId);
  58. if (post is null)
  59. {
  60. return ResultData(null, false, "评论失败,文章不存在!");
  61. }
  62. UserInfoOutputDto user = HttpContext.Session.Get<UserInfoOutputDto>(SessionKey.UserInfo);
  63. comment.Content = comment.Content.Trim().Replace("<p><br></p>", string.Empty);
  64. if (comment.Content.RemoveHtmlTag().Trim().Equals(HttpContext.Session.Get<string>("comment" + comment.PostId)))
  65. {
  66. return ResultData(null, false, "您刚才已经在这篇文章发表过一次评论了,换一篇文章吧,或者换一下评论内容吧!");
  67. }
  68. if (Regex.Match(comment.Content, CommonHelper.ModRegex).Length <= 0)
  69. {
  70. comment.Status = Status.Pended;
  71. }
  72. if (user != null)
  73. {
  74. comment.NickName = user.NickName;
  75. comment.QQorWechat = user.QQorWechat;
  76. comment.Email = user.Email;
  77. if (user.IsAdmin)
  78. {
  79. comment.Status = Status.Pended;
  80. comment.IsMaster = true;
  81. }
  82. }
  83. comment.Content = comment.Content.HtmlSantinizerStandard().ClearImgAttributes();
  84. comment.CommentDate = DateTime.Now;
  85. comment.Browser = comment.Browser ?? Request.Headers[HeaderNames.UserAgent];
  86. comment.IP = HttpContext.Connection.RemoteIpAddress.MapToIPv4().ToString();
  87. Comment com = CommentService.AddEntitySaved(comment.Mapper<Comment>());
  88. if (com != null)
  89. {
  90. HttpContext.Session.Set("comment" + comment.PostId, comment.Content.RemoveHtmlTag().Trim());
  91. var emails = new List<string>();
  92. var email = CommonHelper.SystemSettings["ReceiveEmail"]; //站长邮箱
  93. emails.Add(email);
  94. string content = System.IO.File.ReadAllText(_hostingEnvironment.WebRootPath + "/template/notify.html").Replace("{{title}}", post.Title).Replace("{{time}}", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")).Replace("{{nickname}}", com.NickName).Replace("{{content}}", com.Content);
  95. if (comment.Status == Status.Pended)
  96. {
  97. if (!com.IsMaster)
  98. {
  99. MessageService.AddEntitySaved(new InternalMessage()
  100. {
  101. Title = $"来自【{com.NickName}】的新文章评论",
  102. Content = com.Content,
  103. Link = Url.Action("Details", "Post", new { id = com.PostId, cid = com.Id }, Request.Scheme) + "#comment"
  104. });
  105. }
  106. #if !DEBUG
  107. if (com.ParentId == 0)
  108. {
  109. emails.Add(PostService.GetById(com.PostId).Email);
  110. //新评论,只通知博主和楼主
  111. foreach (var s in emails.Distinct())
  112. {
  113. BackgroundJob.Enqueue(() => CommonHelper.SendMail(CommonHelper.SystemSettings["Domain"] + "|博客文章新评论:", content.Replace("{{link}}", Url.Action("Details", "Post", new { id = com.PostId, cid = com.Id }, Request.Scheme) + "#comment"), s));
  114. }
  115. }
  116. else
  117. {
  118. //通知博主和上层所有关联的评论访客
  119. var pid = CommentService.GetParentCommentIdByChildId(com.Id);
  120. emails = CommentService.GetSelfAndAllChildrenCommentsByParentId(pid).Select(c => c.Email).Except(new List<string> { com.Email }).Distinct().ToList();
  121. string link = Url.Action("Details", "Post", new { id = com.PostId, cid = com.Id }, Request.Scheme) + "#comment";
  122. foreach (var s in emails)
  123. {
  124. BackgroundJob.Enqueue(() => CommonHelper.SendMail($"{CommonHelper.SystemSettings["Domain"]}{CommonHelper.SystemSettings["Title"]}文章评论回复:", content.Replace("{{link}}", link), s));
  125. }
  126. }
  127. #endif
  128. return ResultData(null, true, "评论发表成功,服务器正在后台处理中,这会有一定的延迟,稍后将显示到评论列表中");
  129. }
  130. foreach (var s in emails.Distinct())
  131. {
  132. BackgroundJob.Enqueue(() => CommonHelper.SendMail(CommonHelper.SystemSettings["Domain"] + "|博客文章新评论(待审核):", content.Replace("{{link}}", Url.Action("Details", "Post", new { id = com.PostId, cid = com.Id }, Request.Scheme) + "#comment") + "<p style='color:red;'>(待审核)</p>", s));
  133. }
  134. return ResultData(null, true, "评论成功,待站长审核通过以后将显示");
  135. }
  136. return ResultData(null, false, "评论失败");
  137. }
  138. /// <summary>
  139. /// 评论投票
  140. /// </summary>
  141. /// <param name="id"></param>
  142. /// <returns></returns>
  143. [HttpPost]
  144. public ActionResult CommentVote(int id)
  145. {
  146. Comment cm = CommentService.GetFirstEntity(c => c.Id == id && c.Status == Status.Pended);
  147. if (HttpContext.Session.Get("cm" + id) != null)
  148. {
  149. return ResultData(null, false, "您刚才已经投过票了,感谢您的参与!");
  150. }
  151. if (cm != null)
  152. {
  153. cm.VoteCount++;
  154. CommentService.UpdateEntity(cm);
  155. HttpContext.Session.Set("cm" + id, id.GetBytes());
  156. bool b = CommentService.SaveChanges() > 0;
  157. return ResultData(null, b, b ? "投票成功" : "投票失败");
  158. }
  159. return ResultData(null, false, "非法操作");
  160. }
  161. /// <summary>
  162. /// 获取评论
  163. /// </summary>
  164. /// <param name="id"></param>
  165. /// <param name="page"></param>
  166. /// <param name="size"></param>
  167. /// <param name="cid"></param>
  168. /// <returns></returns>
  169. [HttpPost]
  170. public ActionResult GetComments(int? id, int page = 1, int size = 5, int cid = 0)
  171. {
  172. UserInfoOutputDto user = HttpContext.Session.Get<UserInfoOutputDto>(SessionKey.UserInfo) ?? new UserInfoOutputDto();
  173. int total; //总条数,用于前台分页
  174. if (cid != 0)
  175. {
  176. int pid = CommentService.GetParentCommentIdByChildId(cid);
  177. List<Comment> single = CommentService.GetSelfAndAllChildrenCommentsByParentId(pid).ToList();
  178. if (single.Any())
  179. {
  180. total = 1;
  181. return ResultData(new
  182. {
  183. total,
  184. parentTotal = total,
  185. page,
  186. size,
  187. rows = single.Mapper<IList<CommentViewModel>>()
  188. });
  189. }
  190. }
  191. IList<Comment> parent = CommentService.LoadPageEntities(page, size, out total, c => c.PostId == id && c.ParentId == 0 && (c.Status == Status.Pended || user.IsAdmin), c => c.CommentDate, false).ToList();
  192. if (!parent.Any())
  193. {
  194. return ResultData(null, false, "没有评论");
  195. }
  196. var list = new List<Comment>();
  197. parent.ForEach(c => CommentService.GetSelfAndAllChildrenCommentsByParentId(c.Id).ForEach(result => list.Add(result)));
  198. var qlist = list.Where(c => (c.Status == Status.Pended || user.IsAdmin));
  199. if (total > 0)
  200. {
  201. return ResultData(new
  202. {
  203. total,
  204. parentTotal = total,
  205. page,
  206. size,
  207. rows = qlist.Mapper<IList<CommentViewModel>>()
  208. });
  209. }
  210. return ResultData(null, false, "没有评论");
  211. }
  212. /// <summary>
  213. /// 分页获取评论
  214. /// </summary>
  215. /// <param name="page"></param>
  216. /// <param name="size"></param>
  217. /// <param name="cid"></param>
  218. /// <returns></returns>
  219. [HttpPost]
  220. public ActionResult GetPageComments(int page = 1, int size = 5, int cid = 0)
  221. {
  222. UserInfoOutputDto user = HttpContext.Session.Get<UserInfoOutputDto>(SessionKey.UserInfo) ?? new UserInfoOutputDto();
  223. int total; //总条数,用于前台分页
  224. if (cid != 0)
  225. {
  226. int pid = CommentService.GetParentCommentIdByChildId(cid);
  227. List<Comment> single = CommentService.GetSelfAndAllChildrenCommentsByParentId(pid).ToList();
  228. if (single.Any())
  229. {
  230. total = 1;
  231. return ResultData(new
  232. {
  233. total,
  234. parentTotal = total,
  235. page,
  236. size,
  237. rows = single.Mapper<IList<CommentViewModel>>()
  238. });
  239. }
  240. }
  241. IList<Comment> parent = CommentService.LoadPageEntities(page, size, out total, c => c.ParentId == 0 && (c.Status == Status.Pended || user.IsAdmin), c => c.CommentDate, false).ToList();
  242. if (!parent.Any())
  243. {
  244. return ResultData(null, false, "没有评论");
  245. }
  246. var list = new List<Comment>();
  247. parent.ForEach(c => CommentService.GetSelfAndAllChildrenCommentsByParentId(c.Id).ForEach(result => list.Add(result)));
  248. var qlist = list.Where(c => (c.Status == Status.Pended || user.IsAdmin));
  249. if (total > 0)
  250. {
  251. return ResultData(new
  252. {
  253. total,
  254. parentTotal = total,
  255. page,
  256. size,
  257. rows = qlist.Mapper<IList<CommentViewModel>>()
  258. });
  259. }
  260. return ResultData(null, false, "没有评论");
  261. }
  262. /// <summary>
  263. /// 审核评论
  264. /// </summary>
  265. /// <param name="id"></param>
  266. /// <returns></returns>
  267. [Authority]
  268. public ActionResult Pass(int id)
  269. {
  270. Comment comment = CommentService.GetById(id);
  271. comment.Status = Status.Pended;
  272. Post post = PostService.GetById(comment.PostId);
  273. bool b = CommentService.UpdateEntitySaved(comment);
  274. var pid = comment.ParentId == 0 ? comment.Id : CommentService.GetParentCommentIdByChildId(id);
  275. #if !DEBUG
  276. string content = System.IO.File.ReadAllText(Path.Combine(_hostingEnvironment.WebRootPath, "template", "notify.html")).Replace("{{title}}", post.Title).Replace("{{time}}", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")).Replace("{{nickname}}", comment.NickName).Replace("{{content}}", comment.Content);
  277. var emails = CommentService.GetSelfAndAllChildrenCommentsByParentId(pid).Select(c => c.Email).Distinct().Except(new List<string> { comment.Email, CommonHelper.SystemSettings["ReceiveEmail"] }).ToList();
  278. string link = Url.Action("Details", "Post", new
  279. {
  280. id = comment.PostId,
  281. cid = pid
  282. }, Request.Scheme) + "#comment";
  283. foreach (var email in emails)
  284. {
  285. BackgroundJob.Enqueue(() => CommonHelper.SendMail($"{Request.Host}{CommonHelper.SystemSettings["Title"]}文章评论回复:", content.Replace("{{link}}", link), email));
  286. }
  287. #endif
  288. return ResultData(null, b, b ? "审核通过!" : "审核失败!");
  289. }
  290. /// <summary>
  291. /// 删除评论
  292. /// </summary>
  293. /// <param name="id"></param>
  294. /// <returns></returns>
  295. [Authority]
  296. public ActionResult Delete(int id)
  297. {
  298. var b = CommentService.DeleteEntitiesSaved(CommentService.GetSelfAndAllChildrenCommentsByParentId(id).ToList());
  299. return ResultData(null, b, b ? "删除成功!" : "删除失败!");
  300. }
  301. /// <summary>
  302. /// 获取未审核的评论
  303. /// </summary>
  304. /// <returns></returns>
  305. [Authority]
  306. public ActionResult GetPendingComments(int page = 1, int size = 10)
  307. {
  308. List<CommentOutputDto> list = CommentService.LoadPageEntities<DateTime, CommentOutputDto>(page, size, out int total, c => c.Status == Status.Pending, c => c.CommentDate, false).ToList();
  309. var pageCount = Math.Ceiling(total * 1.0 / size).ToInt32();
  310. return PageResult(list, pageCount, total);
  311. }
  312. }
  313. }