moral.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397
  1. package service
  2. import (
  3. "context"
  4. "fmt"
  5. "go-common/app/admin/main/reply/model"
  6. artmdl "go-common/app/interface/openplatform/article/model"
  7. accmdl "go-common/app/service/main/account/api"
  8. "go-common/app/service/main/archive/api"
  9. arcmdl "go-common/app/service/main/archive/model/archive"
  10. "go-common/library/log"
  11. "time"
  12. "net/url"
  13. "strconv"
  14. )
  15. // filterViolationMsg every two characters, the third character processing for *.
  16. func filterViolationMsg(msg string) string {
  17. s := []rune(msg)
  18. for i := 0; i < len(s); i++ {
  19. if i%3 != 0 {
  20. s[i] = '*'
  21. }
  22. }
  23. return string(s)
  24. }
  25. // 专门给喷子,带狗发送的消息通知, 20181206 针对大忽悠事件
  26. func (s *Service) NotifyTroll(c context.Context, mid int64) (err error) {
  27. var ok bool
  28. if ok, err = s.dao.ExsistsDelMid(c, mid); err != nil || ok {
  29. return
  30. }
  31. title := "评论处理通知"
  32. msg := fmt.Sprintf("您好,根据#{关于规范“主播吴织亚切大忽悠事件”相关言论、信息发布的公告}{\"%s\"},您的相关评论已被清理。对于这一事件的讨论请移步公告中告知的区域进行讨论。", s.conf.Reply.Link)
  33. if err = s.dao.SendReplyDelMsg(c, mid, title, msg, time.Now()); err != nil {
  34. return
  35. }
  36. return s.dao.SetDelMid(c, mid)
  37. }
  38. // TitleLink TitleLink
  39. func (s *Service) TitleLink(c context.Context, oid int64, typ int32) (title, link string, err error) {
  40. switch typ {
  41. case model.SubTypeArchive:
  42. arg := &arcmdl.ArgAid2{
  43. Aid: oid,
  44. }
  45. var m *api.Arc
  46. m, err = s.arcSrv.Archive3(c, arg)
  47. if err != nil || m == nil {
  48. log.Error("s.arcSrv.Archive3(%v) ret:%v error(%v)", arg, m, err)
  49. return
  50. }
  51. if m.RedirectURL != "" {
  52. // NOTE mobile native jump
  53. var uri *url.URL
  54. if uri, err = url.Parse(m.RedirectURL); err == nil {
  55. q := uri.Query()
  56. q.Set("aid", strconv.FormatInt(oid, 10))
  57. uri.RawQuery = q.Encode()
  58. link = uri.String()
  59. }
  60. } else {
  61. link = fmt.Sprintf("http://www.bilibili.com/video/av%d/", oid)
  62. }
  63. title = m.Title
  64. case model.SubTypeTopic:
  65. if title, link, err = s.dao.TopicTitle(c, oid); err != nil {
  66. log.Error("s.noticeDao.Topic(%d) error(%v)", oid, err)
  67. return
  68. }
  69. case model.SubTypeActivity:
  70. if title, link, err = s.dao.TopicTitle(c, oid); err != nil {
  71. log.Error("s.noticeDao.Activity(%d) error(%v)", oid, err)
  72. return
  73. }
  74. case model.SubTypeForbiden:
  75. title, link, err = s.dao.BanTitle(c, oid)
  76. if err != nil {
  77. return
  78. }
  79. case model.SubTypeNotice:
  80. title, link, err = s.dao.NoticeTitle(c, oid)
  81. if err != nil {
  82. return
  83. }
  84. case model.SubTypeActArc:
  85. if title, link, err = s.dao.TopicTitle(c, oid); err != nil {
  86. log.Error("s.noticeDao.ActivitySub(%d) error(%v)", oid, err)
  87. return
  88. }
  89. case model.SubTypeArticle:
  90. arg := &artmdl.ArgAids{
  91. Aids: []int64{oid},
  92. }
  93. var m map[int64]*artmdl.Meta
  94. m, err = s.articleSrv.ArticleMetas(c, arg)
  95. if err != nil || m == nil {
  96. log.Error("s.articleSrv.ArticleMetas(%v) ret:%v error(%v)", arg, m, err)
  97. return
  98. }
  99. if meta, ok := m[oid]; ok {
  100. title = meta.Title
  101. link = fmt.Sprintf("http://www.bilibili.com/read/cv%d", oid)
  102. }
  103. case model.SubTypeLiveVideo:
  104. if title, link, err = s.dao.LiveVideoTitle(c, oid); err != nil {
  105. log.Error("s.noticeDao.LiveSmallVideo(%d) error(%v)", oid, err)
  106. return
  107. }
  108. case model.SubTypeLiveAct:
  109. if title, link, err = s.dao.LiveActivityTitle(c, oid); err != nil {
  110. log.Error("s.noticeDao.LiveActivity(%d) error(%v)", oid, err)
  111. return
  112. }
  113. case model.SubTypeLiveNotice:
  114. // NOTE 忽略直播公告跳转链接
  115. return
  116. case model.SubTypeLivePicture:
  117. if title, link, err = s.dao.LivePictureTitle(c, oid); err != nil {
  118. log.Error("s.noticeDao.LivePiture(%d) error(%v)", oid, err)
  119. return
  120. }
  121. case model.SubTypeCredit:
  122. if title, link, err = s.dao.CreditTitle(c, oid); err != nil {
  123. log.Error("s.noticeDao.Credit(%d) error(%v)", oid, err)
  124. return
  125. }
  126. case model.SubTypeDynamic:
  127. if title, link, err = s.dao.DynamicTitle(c, oid); err != nil {
  128. log.Error("s.noticeDao.Dynamic(%d) error(%v)", oid, err)
  129. return
  130. }
  131. default:
  132. return
  133. }
  134. return
  135. }
  136. func (s *Service) moralAndNotify(c context.Context, rp *model.Reply, moral int32, notify bool, rptMid, adid int64, adname, remark string, reason, freason int32, ftime int64, isPunish bool) {
  137. var err error
  138. title, link, _, msg := s.messageInfo(c, rp)
  139. smsg := []rune(msg)
  140. if len(smsg) > 50 {
  141. smsg = smsg[:50]
  142. }
  143. if moral > 0 {
  144. reason := "发布的评论违规并被管理员删除 - " + string(smsg)
  145. if rptMid > 0 {
  146. reason = "发布的评论被举报并被管理员删除 - " + string(smsg)
  147. }
  148. arg := &accmdl.MoralReq{
  149. Mid: rp.Mid,
  150. Moral: -float64(moral),
  151. Oper: adname,
  152. Reason: reason,
  153. Remark: remark,
  154. }
  155. if _, err = s.accSrv.AddMoral3(c, arg); err != nil {
  156. log.Error("s.accSrv.AddMoral3(%d) error(%v)", rp.Mid, err)
  157. }
  158. }
  159. msg = filterViolationMsg(msg)
  160. if title != "" && link != "" && rptMid > 0 {
  161. if err = s.reportNotify(c, rp, title, link, msg, ftime, reason, freason, isPunish); err != nil {
  162. log.Error("s.reportNotify(%d,%d,%d) error(%v)", rp.Oid, rp.Type, rp.ID, err)
  163. }
  164. }
  165. if ftime != 0 {
  166. if err = s.dao.BlockAccount(c, rp.Mid, ftime, notify, freason, title, rp.Content.Message, link, adname, remark); err != nil {
  167. log.Error("s.reportNotify(%d,%d,%d) error(%v)", rp.Oid, rp.Type, rp.ID, err)
  168. }
  169. }
  170. if err = s.reportNotify(c, rp, title, link, msg, ftime, reason, freason, isPunish); err != nil {
  171. log.Error("s.reportNotify(%d,%d,%d) error(%v)", rp.Oid, rp.Type, rp.ID, err)
  172. }
  173. if !notify {
  174. return
  175. }
  176. if title != "" && link != "" {
  177. // notify message
  178. mt := "评论违规处理通知"
  179. mc := fmt.Sprintf("您好,您在#{%s}{\"%s\"}下的评论 『%s』 ", title, link, msg)
  180. if rptMid > 0 {
  181. mc = fmt.Sprintf("您好,根据用户举报,您在#{%s}{\"%s\"}下的评论 『%s』 ", title, link, msg)
  182. }
  183. if isPunish {
  184. mc += ",已被处罚"
  185. } else {
  186. mc += ",已被移除"
  187. }
  188. // forbidden
  189. if ftime > 0 {
  190. mc += fmt.Sprintf(",并被封禁%d天。", ftime)
  191. } else if ftime == -1 {
  192. mc += ",并被永久封禁。"
  193. } else {
  194. mc += "。"
  195. }
  196. // forbid reason
  197. if ar, ok := model.ForbidReason[freason]; ok {
  198. mc += "理由:" + ar + "。"
  199. // community rules
  200. switch {
  201. case freason == model.ForbidReasonSpoiler || freason == model.ForbidReasonAd || freason == model.ForbidReasonUnlimitedSign || freason == model.ForbidReasonMeaningless:
  202. mc += model.NotifyComRules
  203. case freason == model.ForbidReasonProvoke || freason == model.ForbidReasonAttack:
  204. mc += model.NotifyComProvoke
  205. default:
  206. mc += model.NofityComProhibited
  207. }
  208. } else { // report reason
  209. if ar, ok := model.ReportReason[reason]; ok {
  210. mc += "理由:" + ar + "。"
  211. }
  212. // community rules
  213. switch {
  214. case reason == model.ReportReasonSpoiler || reason == model.ReportReasonAd || reason == model.ReportReasonUnlimitedSign || reason == model.ReportReasonMeaningless:
  215. mc += model.NotifyComRules
  216. case reason == model.ReportReasonUnrelated:
  217. mc += model.NotifyComUnrelated
  218. case reason == model.ReportReasonProvoke || reason == model.ReportReasonAttack:
  219. mc += model.NotifyComProvoke
  220. default:
  221. mc += model.NofityComProhibited
  222. }
  223. }
  224. // send the message
  225. if err = s.dao.SendReplyDelMsg(c, rp.Mid, mt, mc, rp.MTime.Time()); err != nil {
  226. log.Error("s.messageDao.DeleteReply failed, (%d) error(%v)", rp.Mid, err)
  227. }
  228. log.Info("notify oid:%d type:%d rpID:%d reason:%d content:%s", rp.Oid, rp.Type, rp.ID, reason, mc)
  229. } else {
  230. log.Warn("no notify oid:%d type:%d rpid:%d", rp.Oid, rp.Type, rp.ID)
  231. }
  232. }
  233. func (s *Service) messageInfo(c context.Context, rp *model.Reply) (title, link, jump, msg string) {
  234. tmpMsg := []rune(rp.Content.Message)
  235. if len(tmpMsg) > 80 {
  236. msg = string(tmpMsg[:80])
  237. } else {
  238. msg = rp.Content.Message
  239. }
  240. var err error
  241. switch rp.Type {
  242. case model.SubTypeArchive:
  243. arg := &arcmdl.ArgAid2{
  244. Aid: rp.Oid,
  245. }
  246. var m *api.Arc
  247. m, err = s.arcSrv.Archive3(c, arg)
  248. if err != nil || m == nil {
  249. log.Error("s.arcSrv.Archive3(%v) ret:%v error(%v)", arg, m, err)
  250. return
  251. }
  252. if m.RedirectURL != "" {
  253. // NOTE mobile native jump
  254. var uri *url.URL
  255. if uri, err = url.Parse(m.RedirectURL); err == nil {
  256. q := uri.Query()
  257. q.Set("aid", strconv.FormatInt(rp.Oid, 10))
  258. uri.RawQuery = q.Encode()
  259. link = uri.String()
  260. }
  261. } else {
  262. link = fmt.Sprintf("http://www.bilibili.com/video/av%d/", rp.Oid)
  263. }
  264. title = m.Title
  265. case model.SubTypeTopic:
  266. if title, link, err = s.dao.TopicTitle(c, rp.Oid); err != nil {
  267. log.Error("s.noticeDao.Topic(%d) error(%v)", rp.Oid, err)
  268. return
  269. }
  270. case model.SubTypeActivity:
  271. if title, link, err = s.dao.TopicTitle(c, rp.Oid); err != nil {
  272. log.Error("s.noticeDao.Activity(%d) error(%v)", rp.Oid, err)
  273. return
  274. }
  275. case model.SubTypeForbiden:
  276. title, link, err = s.dao.BanTitle(c, rp.Oid)
  277. if err != nil {
  278. return
  279. }
  280. case model.SubTypeNotice:
  281. title, link, err = s.dao.NoticeTitle(c, rp.Oid)
  282. if err != nil {
  283. return
  284. }
  285. case model.SubTypeActArc:
  286. if title, link, err = s.dao.TopicTitle(c, rp.Oid); err != nil {
  287. log.Error("s.noticeDao.ActivitySub(%d) error(%v)", rp.Oid, err)
  288. return
  289. }
  290. case model.SubTypeArticle:
  291. arg := &artmdl.ArgAids{
  292. Aids: []int64{rp.Oid},
  293. }
  294. var m map[int64]*artmdl.Meta
  295. m, err = s.articleSrv.ArticleMetas(c, arg)
  296. if err != nil || m == nil {
  297. log.Error("s.articleSrv.ArticleMetas(%v) ret:%v error(%v)", arg, m, err)
  298. return
  299. }
  300. if meta, ok := m[rp.Oid]; ok {
  301. title = meta.Title
  302. link = fmt.Sprintf("http://www.bilibili.com/read/cv%d", rp.Oid)
  303. }
  304. case model.SubTypeLiveVideo:
  305. if title, link, err = s.dao.LiveVideoTitle(c, rp.Oid); err != nil {
  306. log.Error("s.noticeDao.LiveSmallVideo(%d) error(%v)", rp.Oid, err)
  307. return
  308. }
  309. case model.SubTypeLiveAct:
  310. if title, link, err = s.dao.LiveActivityTitle(c, rp.Oid); err != nil {
  311. log.Error("s.noticeDao.LiveActivity(%d) error(%v)", rp.Oid, err)
  312. return
  313. }
  314. case model.SubTypeLiveNotice:
  315. //if title, link, err = s.noticeDao.LiveNotice(c, rp.Oid); err != nil {
  316. // log.Error("s.noticeDao.LiveNotice(%d) error(%v)", rp.Oid, err)
  317. // return
  318. //}
  319. // NOTE 忽略直播公告跳转链接
  320. return
  321. case model.SubTypeLivePicture:
  322. if title, link, err = s.dao.LivePictureTitle(c, rp.Oid); err != nil {
  323. log.Error("s.noticeDao.LivePiture(%d) error(%v)", rp.Oid, err)
  324. return
  325. }
  326. case model.SubTypeCredit:
  327. if title, link, err = s.dao.CreditTitle(c, rp.Oid); err != nil {
  328. log.Error("s.noticeDao.Credit(%d) error(%v)", rp.Oid, err)
  329. return
  330. }
  331. case model.SubTypeDynamic:
  332. if title, link, err = s.dao.DynamicTitle(c, rp.Oid); err != nil {
  333. log.Error("s.noticeDao.Dynamic(%d) error(%v)", rp.Oid, err)
  334. return
  335. }
  336. default:
  337. return
  338. }
  339. tmp := []rune(title)
  340. if len(tmp) > 40 {
  341. title = string(tmp[:40])
  342. }
  343. jump = fmt.Sprintf("%s#reply%d", link, rp.ID)
  344. log.Info("messageInfo(%d,%d) title:%s link:%s jump:%s msg:%s", rp.Type, rp.Oid, title, link, jump, msg)
  345. return
  346. }
  347. func (s *Service) reportNotify(c context.Context, rp *model.Reply, title, link, msg string, ftime int64, reason, freason int32, isPunish bool) (err error) {
  348. var (
  349. rptUser *model.ReportUser
  350. rptUsers map[int64]*model.ReportUser
  351. )
  352. mt := "举报处理结果通知"
  353. mc := fmt.Sprintf("您好,您在#{%s}{\"%s\"}下举报的评论 『%s』 ", title, link, msg)
  354. if isPunish {
  355. mc += "已被处罚"
  356. } else {
  357. mc += "已被移除"
  358. }
  359. // forbidden
  360. if ftime > 0 {
  361. mc += fmt.Sprintf(",并被封禁%d天。", ftime)
  362. } else if ftime == -1 {
  363. mc += ",该用户已被永久封禁。"
  364. } else {
  365. mc += "。"
  366. }
  367. // forbid reason
  368. if ar, ok := model.ForbidReason[freason]; ok {
  369. mc += "理由:" + ar + "。"
  370. } else if ar, ok := model.ReportReason[reason]; ok {
  371. mc += "理由:" + ar + "。"
  372. }
  373. // community rules
  374. mc += model.NotifyComRulesReport
  375. if rptUsers, err = s.dao.ReportUsers(c, rp.Oid, rp.Type, rp.ID); err != nil {
  376. log.Error("s.dao.ReportUsers(%d,%d,%d) error(%v)", rp.Oid, rp.Type, rp.ID, err)
  377. return
  378. }
  379. for _, rptUser = range rptUsers {
  380. // send the message
  381. if err = s.dao.SendReportAcceptMsg(c, rptUser.Mid, mt, mc, rp.MTime.Time()); err != nil {
  382. log.Error("s.MessageAcceptReport failed, (%d) error(%v)", rp.Mid, err)
  383. }
  384. }
  385. if _, err = s.dao.SetUserReported(c, rp.Oid, rp.Type, rp.ID, rp.MTime.Time()); err != nil {
  386. log.Error("s.dao.SetUserReported(%d, %d, %d) error(%v)", rp.Oid, rp.Type, rp.ID)
  387. }
  388. return
  389. }