You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
318 lines
8.5 KiB
318 lines
8.5 KiB
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 |
|
}
|
|
|