MsgController.cs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336
  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.Mvc;
  13. using Microsoft.EntityFrameworkCore.Internal;
  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 MsgController : BaseController
  26. {
  27. /// <summary>
  28. /// 留言
  29. /// </summary>
  30. public ILeaveMessageService LeaveMessageService { get; set; }
  31. /// <summary>
  32. /// 站内信
  33. /// </summary>
  34. public IInternalMessageService MessageService { get; set; }
  35. public IWebHostEnvironment HostEnvironment { get; set; }
  36. /// <summary>
  37. /// 留言板
  38. /// </summary>
  39. /// <returns></returns>
  40. [ResponseCache(Duration = 600, VaryByHeader = "Cookie"), Route("msg")]
  41. public ActionResult Index()
  42. {
  43. ViewBag.TotalCount = LeaveMessageService.GetQueryNoTracking(m => m.ParentId == 0 && m.Status == Status.Pended).Count();
  44. return CurrentUser.IsAdmin ? View("Index_Admin") : View();
  45. }
  46. /// <summary>
  47. /// 获取留言
  48. /// </summary>
  49. /// <param name="page"></param>
  50. /// <param name="size"></param>
  51. /// <param name="cid"></param>
  52. /// <returns></returns>
  53. public ActionResult GetMsgs(int page = 1, int size = 10, int cid = 0)
  54. {
  55. int total;
  56. if (cid != 0)
  57. {
  58. int pid = LeaveMessageService.GetParentMessageIdByChildId(cid);
  59. var single = LeaveMessageService.GetSelfAndAllChildrenMessagesByParentId(pid).ToList();
  60. if (single.Any())
  61. {
  62. total = 1;
  63. return ResultData(new
  64. {
  65. total,
  66. parentTotal = total,
  67. page,
  68. size,
  69. rows = single.Mapper<IList<LeaveMessageViewModel>>()
  70. });
  71. }
  72. }
  73. var parent = LeaveMessageService.GetPagesNoTracking(page, size, out total, m => m.ParentId == 0 && (m.Status == Status.Pended || CurrentUser.IsAdmin), m => m.PostDate, false);
  74. if (!parent.Any())
  75. {
  76. return ResultData(null, false, "没有留言");
  77. }
  78. var qlist = parent.ToList().SelectMany(c => LeaveMessageService.GetSelfAndAllChildrenMessagesByParentId(c.Id)).Where(c => c.Status == Status.Pended || CurrentUser.IsAdmin);
  79. if (total > 0)
  80. {
  81. return ResultData(new
  82. {
  83. total,
  84. parentTotal = total,
  85. page,
  86. size,
  87. rows = qlist
  88. });
  89. }
  90. return ResultData(null, false, "没有留言");
  91. }
  92. /// <summary>
  93. /// 发表留言
  94. /// </summary>
  95. /// <param name="dto"></param>
  96. /// <returns></returns>
  97. [HttpPost, ValidateAntiForgeryToken]
  98. public ActionResult Put(LeaveMessageInputDto dto)
  99. {
  100. if (Regex.Match(dto.Content, CommonHelper.BanRegex).Length > 0)
  101. {
  102. return ResultData(null, false, "您提交的内容包含敏感词,被禁止发表,请注意改善您的言辞!");
  103. }
  104. dto.Content = dto.Content.Trim().Replace("<p><br></p>", string.Empty);
  105. if (dto.Content.RemoveHtmlTag().Trim().Equals(HttpContext.Session.Get<string>("msg")))
  106. {
  107. return ResultData(null, false, "您刚才已经发表过一次留言了!");
  108. }
  109. var msg = dto.Mapper<LeaveMessage>();
  110. if (Regex.Match(dto.Content, CommonHelper.ModRegex).Length <= 0)
  111. {
  112. msg.Status = Status.Pended;
  113. }
  114. msg.PostDate = DateTime.Now;
  115. var user = HttpContext.Session.Get<UserInfoOutputDto>(SessionKey.UserInfo);
  116. if (user != null)
  117. {
  118. msg.NickName = user.NickName;
  119. msg.QQorWechat = user.QQorWechat;
  120. msg.Email = user.Email;
  121. if (user.IsAdmin)
  122. {
  123. msg.Status = Status.Pended;
  124. msg.IsMaster = true;
  125. }
  126. }
  127. msg.Content = dto.Content.HtmlSantinizerStandard().ClearImgAttributes();
  128. msg.Browser = dto.Browser ?? Request.Headers[HeaderNames.UserAgent];
  129. msg.IP = HttpContext.Connection.RemoteIpAddress.MapToIPv4().ToString();
  130. msg.Location = msg.IP.GetIPLocation().Split("|").Where(s => !int.TryParse(s, out _)).ToHashSet().Join("|");
  131. msg = LeaveMessageService.AddEntitySaved(msg);
  132. if (msg == null)
  133. {
  134. return ResultData(null, false, "留言发表失败!");
  135. }
  136. HttpContext.Session.Set("msg", msg.Content.RemoveHtmlTag().Trim());
  137. var email = CommonHelper.SystemSettings["ReceiveEmail"];
  138. var content = System.IO.File.ReadAllText(HostEnvironment.WebRootPath + "/template/notify.html").Replace("{{title}}", "网站留言板").Replace("{{time}}", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")).Replace("{{nickname}}", msg.NickName).Replace("{{content}}", msg.Content);
  139. if (msg.Status == Status.Pended)
  140. {
  141. if (!msg.IsMaster)
  142. {
  143. MessageService.AddEntitySaved(new InternalMessage()
  144. {
  145. Title = $"来自【{msg.NickName}】的新留言",
  146. Content = msg.Content,
  147. Link = Url.Action("Index", "Msg", new { cid = msg.Id }, Request.Scheme)
  148. });
  149. }
  150. #if !DEBUG
  151. if (msg.ParentId == 0)
  152. {
  153. //新评论,只通知博主
  154. BackgroundJob.Enqueue(() => CommonHelper.SendMail(CommonHelper.SystemSettings["Domain"] + "|博客新留言:", content.Replace("{{link}}", Url.Action("Index", "Msg", new { cid = msg.Id }, Request.Scheme)), email));
  155. }
  156. else
  157. {
  158. //通知博主和上层所有关联的评论访客
  159. var pid = LeaveMessageService.GetParentMessageIdByChildId(msg.Id);
  160. var emails = LeaveMessageService.GetSelfAndAllChildrenMessagesByParentId(pid).Select(c => c.Email).Append(email).Except(new[] { msg.Email }).ToHashSet();
  161. string link = Url.Action("Index", "Msg", new { cid = msg.Id }, Request.Scheme);
  162. foreach (var s in emails)
  163. {
  164. BackgroundJob.Enqueue(() => CommonHelper.SendMail($"{CommonHelper.SystemSettings["Domain"]}{CommonHelper.SystemSettings["Title"]} 留言回复:", content.Replace("{{link}}", link), s));
  165. }
  166. }
  167. #endif
  168. return ResultData(null, true, "留言发表成功,服务器正在后台处理中,这会有一定的延迟,稍后将会显示到列表中!");
  169. }
  170. BackgroundJob.Enqueue(() => CommonHelper.SendMail(CommonHelper.SystemSettings["Domain"] + "|博客新留言(待审核):", content.Replace("{{link}}", Url.Action("Index", "Msg", new
  171. {
  172. cid = msg.Id
  173. }, Request.Scheme)) + "<p style='color:red;'>(待审核)</p>", email));
  174. return ResultData(null, true, "留言发表成功,待站长审核通过以后将显示到列表中!");
  175. }
  176. /// <summary>
  177. /// 审核
  178. /// </summary>
  179. /// <param name="id"></param>
  180. /// <returns></returns>
  181. [Authority]
  182. public ActionResult Pass(int id)
  183. {
  184. var msg = LeaveMessageService.GetById(id);
  185. msg.Status = Status.Pended;
  186. bool b = LeaveMessageService.SaveChanges() > 0;
  187. #if !DEBUG
  188. var pid = msg.ParentId == 0 ? msg.Id : LeaveMessageService.GetParentMessageIdByChildId(id);
  189. var content = System.IO.File.ReadAllText(Path.Combine(HostEnvironment.WebRootPath, "template", "notify.html")).Replace("{{time}}", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")).Replace("{{nickname}}", msg.NickName).Replace("{{content}}", msg.Content);
  190. var emails = LeaveMessageService.GetSelfAndAllChildrenMessagesByParentId(pid).Select(c => c.Email).Except(new List<string> { msg.Email, CurrentUser.Email }).ToHashSet();
  191. var link = Url.Action("Index", "Msg", new { cid = pid }, Request.Scheme);
  192. foreach (var s in emails)
  193. {
  194. BackgroundJob.Enqueue(() => CommonHelper.SendMail($"{Request.Host}{CommonHelper.SystemSettings["Title"]} 留言回复:", content.Replace("{{link}}", link), s));
  195. }
  196. #endif
  197. return ResultData(null, b, b ? "审核通过!" : "审核失败!");
  198. }
  199. /// <summary>
  200. /// 删除留言
  201. /// </summary>
  202. /// <param name="id"></param>
  203. /// <returns></returns>
  204. [Authority]
  205. public ActionResult Delete(int id)
  206. {
  207. var b = LeaveMessageService.DeleteEntitiesSaved(LeaveMessageService.GetSelfAndAllChildrenMessagesByParentId(id).ToList());
  208. return ResultData(null, b, b ? "删除成功!" : "删除失败!");
  209. }
  210. /// <summary>
  211. /// 获取待审核的留言
  212. /// </summary>
  213. /// <returns></returns>
  214. [Authority]
  215. public ActionResult GetPendingMsgs(int page = 1, int size = 10)
  216. {
  217. var list = LeaveMessageService.GetPages<DateTime, LeaveMessageOutputDto>(page, size, out int total, m => m.Status == Status.Pending, l => l.PostDate, false).ToList();
  218. var pageCount = Math.Ceiling(total * 1.0 / size).ToInt32();
  219. return PageResult(list, pageCount, total);
  220. }
  221. #region 站内消息
  222. /// <summary>
  223. /// 已读站内信
  224. /// </summary>
  225. /// <param name="id"></param>
  226. /// <returns></returns>
  227. [Authority]
  228. public ActionResult Read(int id)
  229. {
  230. var msg = MessageService.GetById(id);
  231. msg.Read = true;
  232. MessageService.SaveChanges();
  233. return Content("ok");
  234. }
  235. /// <summary>
  236. /// 标记为未读
  237. /// </summary>
  238. /// <param name="id"></param>
  239. /// <returns></returns>
  240. [Authority]
  241. public ActionResult Unread(int id)
  242. {
  243. var msg = MessageService.GetById(id);
  244. msg.Read = false;
  245. MessageService.SaveChanges();
  246. return Content("ok");
  247. }
  248. /// <summary>
  249. /// 删除站内信
  250. /// </summary>
  251. /// <param name="id"></param>
  252. /// <returns></returns>
  253. [Authority]
  254. public ActionResult DeleteMsg(int id)
  255. {
  256. bool b = MessageService.DeleteByIdSaved(id);
  257. return ResultData(null, b, b ? "站内消息删除成功!" : "站内消息删除失败!");
  258. }
  259. /// <summary>
  260. /// 获取站内信
  261. /// </summary>
  262. /// <param name="page"></param>
  263. /// <param name="size"></param>
  264. /// <returns></returns>
  265. [Authority]
  266. public ActionResult GetInternalMsgs(int page = 1, int size = 10)
  267. {
  268. IEnumerable<InternalMessage> msgs = MessageService.GetPagesNoTracking(page, size, out int total, m => true, m => m.Time, false);
  269. var pageCount = Math.Ceiling(total * 1.0 / size).ToInt32();
  270. return PageResult(msgs, pageCount, total);
  271. }
  272. /// <summary>
  273. /// 获取未读消息
  274. /// </summary>
  275. /// <returns></returns>
  276. [Authority]
  277. public ActionResult GetUnreadMsgs()
  278. {
  279. IEnumerable<InternalMessage> msgs = MessageService.GetQueryNoTracking(m => !m.Read, m => m.Time, false);
  280. return ResultData(msgs);
  281. }
  282. /// <summary>
  283. /// 清除站内信
  284. /// </summary>
  285. /// <returns></returns>
  286. [Authority]
  287. public ActionResult ClearMsgs()
  288. {
  289. MessageService.DeleteEntitySaved(m => m.Read);
  290. return ResultData(null, true, "站内消息清除成功!");
  291. }
  292. /// <summary>
  293. /// 标记为已读
  294. /// </summary>
  295. /// <param name="id"></param>
  296. /// <returns></returns>
  297. [Authority]
  298. public ActionResult MarkRead(int id)
  299. {
  300. var msgs = MessageService.GetQuery(m => m.Id <= id).ToList();
  301. foreach (var t in msgs)
  302. {
  303. t.Read = true;
  304. }
  305. MessageService.SaveChanges();
  306. return ResultData(null);
  307. }
  308. #endregion
  309. }
  310. }