319 lines
8.5 KiB
Go
319 lines
8.5 KiB
Go
|
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
|
|||
|
}
|