dm_manage.go 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  1. package service
  2. import (
  3. "context"
  4. "fmt"
  5. "strconv"
  6. "time"
  7. "go-common/app/interface/main/dm2/model"
  8. "go-common/app/interface/main/dm2/model/oplog"
  9. account "go-common/app/service/main/account/api"
  10. assmdl "go-common/app/service/main/assist/model/assist"
  11. "go-common/library/ecode"
  12. "go-common/library/log"
  13. )
  14. const (
  15. _assistUpperLimit = 100
  16. )
  17. // isAssist check if the user is assist of upper or not.
  18. func (s *Service) isAssist(c context.Context, mid, uid int64) (err error) {
  19. arg := assmdl.ArgAssist{
  20. Mid: mid,
  21. AssistMid: uid,
  22. Type: assmdl.TypeDm,
  23. RealIP: "",
  24. }
  25. res, err := s.assRPC.Assist(c, &arg)
  26. if err != nil {
  27. log.Error("s.assRPC.Assist(%v) error(%v)", arg, err)
  28. return ecode.AccessDenied
  29. }
  30. if res.Assist == 1 && res.Allow == 1 {
  31. return nil
  32. }
  33. if res.Assist == 1 && res.Count > _assistUpperLimit {
  34. return ecode.DMAssistOpToMuch
  35. }
  36. return ecode.AccessDenied
  37. }
  38. // isUpper check if the user is upper.
  39. func (s *Service) isUpper(mid, uid int64) bool {
  40. return mid == uid
  41. }
  42. // EditDMState change dm state
  43. // 0:正常、1:删除、10:用户删除、11:举报脚本删除
  44. func (s *Service) EditDMState(c context.Context, tp int32, mid, oid int64, state int32, dmids []int64, source oplog.Source, operatorType oplog.OperatorType) (err error) {
  45. var (
  46. affect, action int64
  47. )
  48. if source <= 0 {
  49. source = oplog.SourceUp
  50. }
  51. if operatorType <= 0 {
  52. operatorType = oplog.OperatorUp
  53. }
  54. sub, err := s.subject(c, tp, oid)
  55. if err != nil {
  56. return
  57. }
  58. switch state {
  59. case model.StateNormal, model.StateDelete:
  60. var isAssist bool
  61. if !s.isUpper(sub.Mid, mid) {
  62. if err = s.isAssist(c, sub.Mid, mid); err != nil {
  63. return
  64. }
  65. }
  66. affect, err = s.dao.UpdateDMStat(c, tp, oid, state, dmids)
  67. if err != nil {
  68. log.Error("s.dao.UpdateDMStat(oid:%d state:%d dmids:%v) error(%v)", oid, state, dmids, err)
  69. return
  70. }
  71. if affect > 0 {
  72. if state == model.StateDelete && sub.IsMonitoring() {
  73. s.oidLock.Lock()
  74. s.moniOidMap[sub.Oid] = struct{}{}
  75. s.oidLock.Unlock()
  76. }
  77. s.OpLog(c, oid, mid, time.Now().Unix(), int(tp), dmids, "status", "", strconv.FormatInt(int64(state), 10), "更新弹幕状态", source, operatorType)
  78. if state == model.StateDelete {
  79. action = assmdl.ActDelete
  80. affect = -affect
  81. }
  82. if sub.Count+affect < 0 {
  83. affect = -sub.Count
  84. }
  85. if _, err = s.dao.IncrSubjectCount(c, tp, oid, affect); err != nil {
  86. return
  87. }
  88. if isAssist {
  89. for _, dmid := range dmids {
  90. s.addAssistLog(sub.Mid, mid, oid, action, dmid)
  91. }
  92. }
  93. }
  94. case model.StateUserDelete:
  95. affect, err = s.dao.UpdateUserDMStat(c, tp, oid, mid, state, dmids)
  96. if err != nil {
  97. log.Error("s.dao.UpdateUserDMStat(mid:%d oid:%d state:%d dmids:%v) error(%v)", mid, oid, state, dmids, err)
  98. return
  99. }
  100. if affect > 0 {
  101. if sub.IsMonitoring() {
  102. s.oidLock.Lock()
  103. s.moniOidMap[sub.Oid] = struct{}{}
  104. s.oidLock.Unlock()
  105. }
  106. s.OpLog(c, oid, mid, time.Now().Unix(), int(tp), dmids, "status", "", fmt.Sprint(state), "更新弹幕状态", source, operatorType)
  107. affect = -affect
  108. if sub.Count+affect < 0 {
  109. affect = -sub.Count
  110. }
  111. if _, err = s.dao.IncrSubjectCount(c, tp, oid, affect); err != nil {
  112. return
  113. }
  114. }
  115. case model.StateScriptDelete:
  116. affect, err = s.dao.UpdateDMStat(c, tp, oid, state, dmids)
  117. if err != nil {
  118. log.Error("s.dao.UpdateDMStat(oid:%d state:%d dmids:%v) error(%v)", oid, state, dmids, err)
  119. return
  120. }
  121. if affect > 0 {
  122. if sub.IsMonitoring() {
  123. s.oidLock.Lock()
  124. s.moniOidMap[sub.Oid] = struct{}{}
  125. s.oidLock.Unlock()
  126. }
  127. s.OpLog(c, oid, mid, time.Now().Unix(), int(tp), dmids, "status", "", fmt.Sprint(state), "更新弹幕状态", source, operatorType)
  128. affect = -affect
  129. if sub.Count+affect < 0 {
  130. affect = -sub.Count
  131. }
  132. if _, err = s.dao.IncrSubjectCount(c, tp, oid, affect); err != nil {
  133. return
  134. }
  135. }
  136. default:
  137. err = ecode.RequestErr
  138. }
  139. return
  140. }
  141. // EditDMPool edit dm pool.
  142. func (s *Service) EditDMPool(c context.Context, tp int32, mid, oid int64, pool int32, ids []int64, source oplog.Source, operatorType oplog.OperatorType) (err error) {
  143. var (
  144. isAssist bool
  145. affect int64
  146. )
  147. if pool != model.PoolNormal && pool != model.PoolSubtitle {
  148. err = ecode.RequestErr
  149. return
  150. }
  151. // pool 2 dm can't move to other pool
  152. dmids := make([]int64, 0, len(ids))
  153. indexs, _, err := s.dao.IndexsByid(c, tp, oid, ids)
  154. for dmid, index := range indexs {
  155. if index.Pool != model.PoolSpecial {
  156. dmids = append(dmids, dmid)
  157. }
  158. }
  159. if len(dmids) <= 0 {
  160. return
  161. }
  162. if source <= 0 {
  163. source = oplog.SourceUp
  164. }
  165. if operatorType <= 0 {
  166. operatorType = oplog.OperatorUp
  167. }
  168. sub, err := s.subject(c, tp, oid)
  169. if err != nil {
  170. return
  171. }
  172. // maximum batch move count to subtitle pool is 300 when the rank of
  173. // user is equal or less than 15000
  174. if pool == model.PoolSubtitle {
  175. var (
  176. reply *account.ProfileReply
  177. )
  178. if reply, err = s.accountRPC.Profile3(c, &account.MidReq{Mid: mid}); err != nil {
  179. log.Error("accRPC.Profile3(%v) error(%v)", mid, err)
  180. return
  181. }
  182. if reply.Profile.Rank <= 15000 && int(sub.MoveCnt)+len(dmids) > 300 {
  183. err = ecode.DMPoolLimit
  184. return
  185. }
  186. }
  187. if !s.isUpper(sub.Mid, mid) {
  188. if err = s.isAssist(c, sub.Mid, mid); err != nil {
  189. return
  190. }
  191. }
  192. if sub.Childpool < pool {
  193. if _, err = s.dao.UpSubjectPool(c, tp, oid, pool); err != nil {
  194. return
  195. }
  196. }
  197. if affect, err = s.dao.UpdateDMPool(c, tp, oid, pool, dmids); err != nil {
  198. log.Error("s.dao.UpdateDMPool(oid:%d pool:%d dmids:%v) error(%v)", oid, pool, dmids, err)
  199. return
  200. }
  201. if affect > 0 {
  202. if pool == model.PoolNormal {
  203. s.dao.IncrSubMoveCount(c, sub.Type, sub.Oid, -affect) // NOTE update move_count,ignore error
  204. } else {
  205. s.dao.IncrSubMoveCount(c, sub.Type, sub.Oid, affect) // NOTE update move_count,ignore error
  206. }
  207. s.OpLog(c, oid, mid, time.Now().Unix(), int(tp), dmids, "pool", "", strconv.FormatInt(int64(pool), 10), "弹幕池变更", source, operatorType)
  208. }
  209. if isAssist {
  210. for _, dmid := range dmids {
  211. s.addAssistLog(sub.Mid, mid, oid, assmdl.ActProtect, dmid)
  212. }
  213. }
  214. return
  215. }
  216. // EditDMAttr update dm attribute.
  217. func (s *Service) EditDMAttr(c context.Context, tp int32, mid, oid int64, bit uint, value int32, dmids []int64, source oplog.Source, operatorType oplog.OperatorType) (affectIds []int64, err error) {
  218. var isAssist bool
  219. affectIds = make([]int64, 0, len(dmids))
  220. if value != model.AttrNo && value != model.AttrYes {
  221. err = ecode.RequestErr
  222. return
  223. }
  224. if source <= 0 {
  225. source = oplog.SourceUp
  226. }
  227. if operatorType <= 0 {
  228. operatorType = oplog.OperatorUp
  229. }
  230. sub, err := s.subject(c, tp, oid)
  231. if err != nil {
  232. return
  233. }
  234. if !s.isUpper(sub.Mid, mid) {
  235. if err = s.isAssist(c, sub.Mid, mid); err != nil {
  236. return
  237. }
  238. }
  239. idxMap, _, err := s.dao.IndexsByid(c, tp, oid, dmids)
  240. if err != nil {
  241. return
  242. }
  243. for dmid, idx := range idxMap {
  244. if !model.IsDMEditAble(idx.State) {
  245. continue
  246. }
  247. idx.AttrSet(value, bit)
  248. if _, err = s.dao.UpdateDMAttr(c, tp, oid, dmid, idx.Attr); err != nil {
  249. continue
  250. }
  251. s.OpLog(c, oid, mid, time.Now().Unix(), int(tp), []int64{dmid}, "attribute", "", fmt.Sprintf("bit:%d,value:%d", bit, value), "弹幕保护状态变更", source, operatorType)
  252. if isAssist {
  253. s.addAssistLog(sub.Mid, mid, oid, assmdl.ActProtect, dmid)
  254. }
  255. affectIds = append(affectIds, dmid)
  256. }
  257. return
  258. }
  259. func (s *Service) addAssistLog(mid, assistMid, oid, action, dmid int64) {
  260. ct, err := s.dao.Content(context.TODO(), oid, dmid)
  261. if err != nil || ct == nil {
  262. return
  263. }
  264. detail := ct.Msg
  265. if len([]rune(ct.Msg)) > 50 {
  266. detail = string([]rune(ct.Msg)[:50])
  267. }
  268. arg := &assmdl.ArgAssistLogAdd{
  269. Mid: mid,
  270. AssistMid: assistMid,
  271. Type: assmdl.TypeDm,
  272. Action: action,
  273. SubjectID: oid,
  274. ObjectID: fmt.Sprint(dmid),
  275. Detail: detail,
  276. }
  277. select {
  278. case s.assistLogChan <- arg:
  279. default:
  280. log.Error("assistLogChan is full")
  281. }
  282. }
  283. func (s *Service) assistLogproc() {
  284. for arg := range s.assistLogChan {
  285. if err := s.assRPC.AssistLogAdd(context.TODO(), arg); err != nil {
  286. log.Error("assRPC.AssistLogAdd(%v) error(%v)", arg, err)
  287. } else {
  288. log.Info("assRPC.AssistLogAdd(%v) success", arg)
  289. }
  290. }
  291. }
  292. // updateMonitorCnt update mcount of subject.
  293. func (s *Service) updateMonitorCnt(c context.Context, sub *model.Subject) (err error) {
  294. var state, mcount int64
  295. if sub.AttrVal(model.AttrSubMonitorBefore) == model.AttrYes {
  296. state = int64(model.StateMonitorBefore)
  297. } else if sub.AttrVal(model.AttrSubMonitorAfter) == model.AttrYes {
  298. state = int64(model.StateMonitorAfter)
  299. } else {
  300. return
  301. }
  302. if mcount, err = s.dao.DMCount(c, sub.Type, sub.Oid, []int64{state}); err != nil {
  303. return
  304. }
  305. _, err = s.dao.UpSubjectMCount(c, sub.Type, sub.Oid, mcount)
  306. return
  307. }