go-common/app/interface/main/dm2/service/dm_manage.go
2019-04-22 18:49:16 +08:00

319 lines
8.5 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package service
import (
"context"
"fmt"
"strconv"
"time"
"go-common/app/interface/main/dm2/model"
"go-common/app/interface/main/dm2/model/oplog"
account "go-common/app/service/main/account/api"
assmdl "go-common/app/service/main/assist/model/assist"
"go-common/library/ecode"
"go-common/library/log"
)
const (
_assistUpperLimit = 100
)
// isAssist check if the user is assist of upper or not.
func (s *Service) isAssist(c context.Context, mid, uid int64) (err error) {
arg := assmdl.ArgAssist{
Mid: mid,
AssistMid: uid,
Type: assmdl.TypeDm,
RealIP: "",
}
res, err := s.assRPC.Assist(c, &arg)
if err != nil {
log.Error("s.assRPC.Assist(%v) error(%v)", arg, err)
return ecode.AccessDenied
}
if res.Assist == 1 && res.Allow == 1 {
return nil
}
if res.Assist == 1 && res.Count > _assistUpperLimit {
return ecode.DMAssistOpToMuch
}
return ecode.AccessDenied
}
// isUpper check if the user is upper.
func (s *Service) isUpper(mid, uid int64) bool {
return mid == uid
}
// EditDMState change dm state
// 0正常、1删除、10用户删除、11举报脚本删除
func (s *Service) EditDMState(c context.Context, tp int32, mid, oid int64, state int32, dmids []int64, source oplog.Source, operatorType oplog.OperatorType) (err error) {
var (
affect, action int64
)
if source <= 0 {
source = oplog.SourceUp
}
if operatorType <= 0 {
operatorType = oplog.OperatorUp
}
sub, err := s.subject(c, tp, oid)
if err != nil {
return
}
switch state {
case model.StateNormal, model.StateDelete:
var isAssist bool
if !s.isUpper(sub.Mid, mid) {
if err = s.isAssist(c, sub.Mid, mid); err != nil {
return
}
}
affect, err = s.dao.UpdateDMStat(c, tp, oid, state, dmids)
if err != nil {
log.Error("s.dao.UpdateDMStat(oid:%d state:%d dmids:%v) error(%v)", oid, state, dmids, err)
return
}
if affect > 0 {
if state == model.StateDelete && sub.IsMonitoring() {
s.oidLock.Lock()
s.moniOidMap[sub.Oid] = struct{}{}
s.oidLock.Unlock()
}
s.OpLog(c, oid, mid, time.Now().Unix(), int(tp), dmids, "status", "", strconv.FormatInt(int64(state), 10), "更新弹幕状态", source, operatorType)
if state == model.StateDelete {
action = assmdl.ActDelete
affect = -affect
}
if sub.Count+affect < 0 {
affect = -sub.Count
}
if _, err = s.dao.IncrSubjectCount(c, tp, oid, affect); err != nil {
return
}
if isAssist {
for _, dmid := range dmids {
s.addAssistLog(sub.Mid, mid, oid, action, dmid)
}
}
}
case model.StateUserDelete:
affect, err = s.dao.UpdateUserDMStat(c, tp, oid, mid, state, dmids)
if err != nil {
log.Error("s.dao.UpdateUserDMStat(mid:%d oid:%d state:%d dmids:%v) error(%v)", mid, oid, state, dmids, err)
return
}
if affect > 0 {
if sub.IsMonitoring() {
s.oidLock.Lock()
s.moniOidMap[sub.Oid] = struct{}{}
s.oidLock.Unlock()
}
s.OpLog(c, oid, mid, time.Now().Unix(), int(tp), dmids, "status", "", fmt.Sprint(state), "更新弹幕状态", source, operatorType)
affect = -affect
if sub.Count+affect < 0 {
affect = -sub.Count
}
if _, err = s.dao.IncrSubjectCount(c, tp, oid, affect); err != nil {
return
}
}
case model.StateScriptDelete:
affect, err = s.dao.UpdateDMStat(c, tp, oid, state, dmids)
if err != nil {
log.Error("s.dao.UpdateDMStat(oid:%d state:%d dmids:%v) error(%v)", oid, state, dmids, err)
return
}
if affect > 0 {
if sub.IsMonitoring() {
s.oidLock.Lock()
s.moniOidMap[sub.Oid] = struct{}{}
s.oidLock.Unlock()
}
s.OpLog(c, oid, mid, time.Now().Unix(), int(tp), dmids, "status", "", fmt.Sprint(state), "更新弹幕状态", source, operatorType)
affect = -affect
if sub.Count+affect < 0 {
affect = -sub.Count
}
if _, err = s.dao.IncrSubjectCount(c, tp, oid, affect); err != nil {
return
}
}
default:
err = ecode.RequestErr
}
return
}
// EditDMPool edit dm pool.
func (s *Service) EditDMPool(c context.Context, tp int32, mid, oid int64, pool int32, ids []int64, source oplog.Source, operatorType oplog.OperatorType) (err error) {
var (
isAssist bool
affect int64
)
if pool != model.PoolNormal && pool != model.PoolSubtitle {
err = ecode.RequestErr
return
}
// pool 2 dm can't move to other pool
dmids := make([]int64, 0, len(ids))
indexs, _, err := s.dao.IndexsByid(c, tp, oid, ids)
for dmid, index := range indexs {
if index.Pool != model.PoolSpecial {
dmids = append(dmids, dmid)
}
}
if len(dmids) <= 0 {
return
}
if source <= 0 {
source = oplog.SourceUp
}
if operatorType <= 0 {
operatorType = oplog.OperatorUp
}
sub, err := s.subject(c, tp, oid)
if err != nil {
return
}
// maximum batch move count to subtitle pool is 300 when the rank of
// user is equal or less than 15000
if pool == model.PoolSubtitle {
var (
reply *account.ProfileReply
)
if reply, err = s.accountRPC.Profile3(c, &account.MidReq{Mid: mid}); err != nil {
log.Error("accRPC.Profile3(%v) error(%v)", mid, err)
return
}
if reply.Profile.Rank <= 15000 && int(sub.MoveCnt)+len(dmids) > 300 {
err = ecode.DMPoolLimit
return
}
}
if !s.isUpper(sub.Mid, mid) {
if err = s.isAssist(c, sub.Mid, mid); err != nil {
return
}
}
if sub.Childpool < pool {
if _, err = s.dao.UpSubjectPool(c, tp, oid, pool); err != nil {
return
}
}
if affect, err = s.dao.UpdateDMPool(c, tp, oid, pool, dmids); err != nil {
log.Error("s.dao.UpdateDMPool(oid:%d pool:%d dmids:%v) error(%v)", oid, pool, dmids, err)
return
}
if affect > 0 {
if pool == model.PoolNormal {
s.dao.IncrSubMoveCount(c, sub.Type, sub.Oid, -affect) // NOTE update move_count,ignore error
} else {
s.dao.IncrSubMoveCount(c, sub.Type, sub.Oid, affect) // NOTE update move_count,ignore error
}
s.OpLog(c, oid, mid, time.Now().Unix(), int(tp), dmids, "pool", "", strconv.FormatInt(int64(pool), 10), "弹幕池变更", source, operatorType)
}
if isAssist {
for _, dmid := range dmids {
s.addAssistLog(sub.Mid, mid, oid, assmdl.ActProtect, dmid)
}
}
return
}
// EditDMAttr update dm attribute.
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) {
var isAssist bool
affectIds = make([]int64, 0, len(dmids))
if value != model.AttrNo && value != model.AttrYes {
err = ecode.RequestErr
return
}
if source <= 0 {
source = oplog.SourceUp
}
if operatorType <= 0 {
operatorType = oplog.OperatorUp
}
sub, err := s.subject(c, tp, oid)
if err != nil {
return
}
if !s.isUpper(sub.Mid, mid) {
if err = s.isAssist(c, sub.Mid, mid); err != nil {
return
}
}
idxMap, _, err := s.dao.IndexsByid(c, tp, oid, dmids)
if err != nil {
return
}
for dmid, idx := range idxMap {
if !model.IsDMEditAble(idx.State) {
continue
}
idx.AttrSet(value, bit)
if _, err = s.dao.UpdateDMAttr(c, tp, oid, dmid, idx.Attr); err != nil {
continue
}
s.OpLog(c, oid, mid, time.Now().Unix(), int(tp), []int64{dmid}, "attribute", "", fmt.Sprintf("bit:%d,value:%d", bit, value), "弹幕保护状态变更", source, operatorType)
if isAssist {
s.addAssistLog(sub.Mid, mid, oid, assmdl.ActProtect, dmid)
}
affectIds = append(affectIds, dmid)
}
return
}
func (s *Service) addAssistLog(mid, assistMid, oid, action, dmid int64) {
ct, err := s.dao.Content(context.TODO(), oid, dmid)
if err != nil || ct == nil {
return
}
detail := ct.Msg
if len([]rune(ct.Msg)) > 50 {
detail = string([]rune(ct.Msg)[:50])
}
arg := &assmdl.ArgAssistLogAdd{
Mid: mid,
AssistMid: assistMid,
Type: assmdl.TypeDm,
Action: action,
SubjectID: oid,
ObjectID: fmt.Sprint(dmid),
Detail: detail,
}
select {
case s.assistLogChan <- arg:
default:
log.Error("assistLogChan is full")
}
}
func (s *Service) assistLogproc() {
for arg := range s.assistLogChan {
if err := s.assRPC.AssistLogAdd(context.TODO(), arg); err != nil {
log.Error("assRPC.AssistLogAdd(%v) error(%v)", arg, err)
} else {
log.Info("assRPC.AssistLogAdd(%v) success", arg)
}
}
}
// updateMonitorCnt update mcount of subject.
func (s *Service) updateMonitorCnt(c context.Context, sub *model.Subject) (err error) {
var state, mcount int64
if sub.AttrVal(model.AttrSubMonitorBefore) == model.AttrYes {
state = int64(model.StateMonitorBefore)
} else if sub.AttrVal(model.AttrSubMonitorAfter) == model.AttrYes {
state = int64(model.StateMonitorAfter)
} else {
return
}
if mcount, err = s.dao.DMCount(c, sub.Type, sub.Oid, []int64{state}); err != nil {
return
}
_, err = s.dao.UpSubjectMCount(c, sub.Type, sub.Oid, mcount)
return
}