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.
368 lines
9.5 KiB
368 lines
9.5 KiB
package service |
|
|
|
import ( |
|
"context" |
|
"fmt" |
|
|
|
"go-common/app/interface/main/dm2/model" |
|
account "go-common/app/service/main/account/api" |
|
arcMdl "go-common/app/service/main/archive/model/archive" |
|
coinmdl "go-common/app/service/main/coin/model" |
|
relation "go-common/app/service/main/relation/model" |
|
"go-common/library/ecode" |
|
"go-common/library/log" |
|
) |
|
|
|
// BuyAdvance 购买高级弹幕 |
|
func (s *Service) BuyAdvance(c context.Context, mid, cid int64, mode string) (err error) { |
|
var ( |
|
refund = int64(1) |
|
coin = model.AdvSPCoin |
|
reason = model.AdvSPCoinReason |
|
advPermit int8 |
|
) |
|
if !s.dao.AddAdvanceLock(c, cid, mid) { |
|
return |
|
} |
|
defer s.dao.DelAdvanceLock(c, cid, mid) |
|
reply, err := s.accountRPC.Info3(c, &account.MidReq{Mid: mid}) |
|
if err != nil { |
|
log.Error("s.accRPC.Info3(%d) error(%v)", mid, err) |
|
return |
|
} |
|
if s.isSuperUser(reply.GetInfo().GetRank()) { |
|
return |
|
} |
|
if mode != model.AdvSpeMode { // pool=2 弹幕 |
|
coin = model.AdvCoin |
|
reason = model.AdvCoinReason |
|
} |
|
typ, err := s.dao.AdvanceType(c, cid, mid, mode) |
|
if err != nil { |
|
log.Error("dao.AdvanceType(%d,%d,%s) error(%v)", cid, mid, mode, err) |
|
return |
|
} |
|
sub, err := s.subject(c, model.SubTypeVideo, cid) |
|
if err != nil { |
|
return |
|
} |
|
if typ != "" { // 已有购买记录 |
|
if typ == model.AdvTypeRequest && mid != sub.Mid { |
|
err = ecode.DMAdvConfirm |
|
} else { |
|
err = ecode.DMAdvBought |
|
} |
|
return |
|
} |
|
if mid != sub.Mid { |
|
advPermit, err = s.dao.UpperConfig(c, sub.Mid) |
|
if err != nil { |
|
return |
|
} |
|
if err = s.checkAdvancePermit(c, advPermit, sub.Mid, mid); err != nil { |
|
return |
|
} |
|
} |
|
typ = model.AdvTypeRequest |
|
if sub.Mid == mid { |
|
typ = model.AdvTypeBuy |
|
} |
|
coins, err := s.coinRPC.UserCoins(c, &coinmdl.ArgCoinInfo{Mid: mid}) |
|
if err != nil { |
|
log.Error("coinRPC.UserCoins(%v) error(%v)", mid, err) |
|
return |
|
} |
|
if coins < float64(coin) { |
|
err = ecode.LackOfCoins |
|
return |
|
} |
|
if _, err = s.dao.BuyAdvance(c, mid, cid, sub.Mid, refund, typ, mode); err != nil { |
|
return |
|
} |
|
if _, err = s.coinRPC.ModifyCoin(c, &coinmdl.ArgModifyCoin{Mid: mid, Count: -float64(coin), Reason: reason, CheckZero: 1}); err != nil { |
|
log.Error("coinRPC.ModifyCoin(%v,%v,%v) error(%v)", mid, coin, reason, err) |
|
return |
|
} |
|
if err = s.dao.DelAdvCache(c, mid, cid, mode); err != nil { |
|
return |
|
} |
|
s.cache.Do(c, func(ctx context.Context) { |
|
arc, err := s.arcRPC.Archive3(ctx, &arcMdl.ArgAid2{Aid: sub.Pid}) |
|
if err != nil { |
|
log.Error("s.arcRPC.Archive3(aid:%d) error(%v)", sub.Pid, err) |
|
return |
|
} |
|
title := "您收到了一条高级弹幕请求" |
|
content := fmt.Sprintf(`您的稿件《%s》收到了一条高级弹幕请求,#{立即处理}{"https://member.bilibili.com/v/#/danmu/report/advance"}`, arc.Title) |
|
s.dao.SendNotify(ctx, title, content, "4", []int64{sub.Mid}) |
|
}) |
|
return |
|
} |
|
|
|
func (s *Service) checkAdvancePermit(c context.Context, advPermit int8, upid, mid int64) (err error) { |
|
|
|
switch advPermit { |
|
case model.AdvPermitAll: |
|
return |
|
case model.AdvPermitFollower, model.AdvPermitAttention: |
|
var ( |
|
arg = &relation.ArgMid{Mid: upid} |
|
res = make([]*relation.Following, 0) |
|
follower *relation.Following |
|
) |
|
if res, err = s.relRPC.Followers(c, arg); err != nil { |
|
log.Error("relRPC.Followers(%+v) error(%v)", arg, err) |
|
return |
|
} |
|
for _, v := range res { |
|
if v.Mid == mid { |
|
follower = v |
|
break |
|
} |
|
} |
|
if follower == nil { |
|
err = ecode.DMAdvNotAllow |
|
return |
|
} |
|
if advPermit == model.AdvPermitAttention && follower.Attribute != 6 { // Attribute=6为相互关注 |
|
err = ecode.DMAdvNotAllow |
|
return |
|
} |
|
case model.AdvPermitForbid: |
|
err = ecode.DMAdvNotAllow |
|
return |
|
} |
|
return |
|
} |
|
|
|
// AdvanceState 高级弹幕状态 |
|
func (s *Service) AdvanceState(c context.Context, mid, cid int64, mode string) (state *model.AdvState, err error) { |
|
state = &model.AdvState{ |
|
Accept: true, |
|
Coins: model.AdvSPCoin, |
|
Confirm: model.AdvStatConfirmDefault, |
|
} |
|
if mode == model.AdvMode { // pool=2 弹幕 |
|
state.Coins = model.AdvCoin |
|
} |
|
reply, err := s.accountRPC.Info3(c, &account.MidReq{Mid: mid}) |
|
if err != nil { |
|
log.Error("s.accRPC.Info3(%d) error(%v)", mid, err) |
|
return |
|
} |
|
if s.isSuperUser(reply.GetInfo().GetRank()) { |
|
state.HasBuy = true |
|
state.Confirm = model.AdvStatConfirmAgree |
|
return |
|
} |
|
typ, err := s.dao.AdvanceType(c, cid, mid, mode) |
|
if err != nil { |
|
return |
|
} |
|
switch typ { |
|
case model.AdvTypeAccept, model.AdvTypeBuy: // 已通过 |
|
state.Confirm = model.AdvStatConfirmAgree |
|
state.HasBuy = true |
|
case model.AdvTypeRequest: // 正在确认中 |
|
state.Confirm = model.AdvStatConfirmRequest |
|
state.HasBuy = true |
|
case model.AdvTypeDeny: // up 主拒绝 |
|
state.Confirm = model.AdvStatConfirmDeny |
|
state.HasBuy = true |
|
} |
|
return |
|
} |
|
|
|
// Advances 高级弹幕申请列表 |
|
func (s *Service) Advances(c context.Context, mid int64) (res []*model.Advance, err error) { |
|
var ( |
|
cidMap = make(map[int64]bool) |
|
midMap = make(map[int64]bool) |
|
mids = make([]int64, 0) |
|
cidAidMap = make(map[int64]int64) |
|
aids = make([]int64, 0) |
|
) |
|
list, err := s.dao.Advances(c, mid) |
|
if err != nil { |
|
log.Error("dao.Advances(%d) error(%v)", mid, err) |
|
return |
|
} |
|
if len(list) == 0 { |
|
return |
|
} |
|
res = make([]*model.Advance, 0, len(list)) |
|
for _, l := range list { |
|
if _, ok := midMap[l.Mid]; !ok { |
|
midMap[l.Mid] = true |
|
mids = append(mids, l.Mid) |
|
} |
|
cidMap[l.Cid] = true |
|
} |
|
for cid := range cidMap { // get cids->aids |
|
var sub *model.Subject |
|
if sub, err = s.subject(c, model.SubTypeVideo, cid); err != nil { |
|
log.Error("s.subject(%d) error(%v)", cid, err) |
|
return |
|
} |
|
if sub == nil { |
|
err = ecode.NothingFound |
|
continue |
|
} |
|
if _, ok := cidAidMap[sub.Oid]; !ok { |
|
cidAidMap[sub.Oid] = sub.Pid |
|
aids = append(aids, sub.Pid) |
|
} |
|
} |
|
arcs, err := s.archiveInfos(c, aids) // get archiveinfos |
|
if err != nil { |
|
return |
|
} |
|
reply, err := s.accountRPC.Infos3(c, &account.MidsReq{ |
|
Mids: mids, |
|
}) |
|
if err != nil { |
|
log.Error("s.accRPC.Infos3(%v) error(%v)", mids, err) |
|
return |
|
} |
|
for _, v := range list { |
|
if aid, ok := cidAidMap[v.Cid]; ok { |
|
v.Aid = aid |
|
} else { |
|
continue |
|
} |
|
if archive, ok := arcs[v.Aid]; ok { |
|
v.Title = archive.Title |
|
v.Cover = archive.Pic |
|
} |
|
if user, ok := reply.GetInfos()[v.Mid]; ok { |
|
v.Uname = user.Name |
|
} |
|
res = append(res, v) |
|
} |
|
return |
|
} |
|
|
|
// PassAdvance 通过高级弹幕申请 |
|
func (s *Service) PassAdvance(c context.Context, mid, id int64) (err error) { |
|
adv, err := s.dao.Advance(c, mid, id) |
|
if err != nil { |
|
log.Error("dao.Advance(%d,%d) error(%v)", mid, id, err) |
|
return |
|
} |
|
if adv == nil || adv.Type == model.AdvTypeDeny { |
|
err = ecode.DMAdvNoFound |
|
return |
|
} |
|
if adv.Type == model.AdvTypeAccept { |
|
return |
|
} |
|
if _, err = s.dao.UpdateAdvType(c, id, model.AdvTypeAccept); err != nil { |
|
log.Error("dao.UpdateAdvType(%d,%d,%s) error(%v)", mid, id, model.AdvTypeAccept, err) |
|
return |
|
} |
|
if err = s.dao.DelAdvCache(c, adv.Mid, adv.Cid, adv.Mode); err != nil { |
|
log.Error("dao.DelAdvCache(%+v) error(%v)", adv, err) |
|
} |
|
return |
|
} |
|
|
|
// DenyAdvance 拒绝高级弹幕申请 |
|
func (s *Service) DenyAdvance(c context.Context, mid, id int64) (err error) { |
|
var ( |
|
coin float64 |
|
reason string |
|
af int64 |
|
) |
|
adv, err := s.dao.Advance(c, mid, id) |
|
if err != nil { |
|
log.Error("dao.Advance(%d,%d) error(%v)", mid, id, err) |
|
return |
|
} |
|
if adv == nil { |
|
return |
|
} |
|
if len(adv.Type) == 0 || adv.Type == model.AdvTypeDeny { |
|
err = ecode.DMAdvNoFound |
|
return |
|
} |
|
if af, err = s.dao.UpdateAdvType(c, id, model.AdvTypeDeny); err != nil { |
|
log.Error("dao.UpdateAdvType(%d) error(%v)", id, err) |
|
return |
|
} |
|
if err = s.dao.DelAdvCache(c, adv.Mid, adv.Cid, adv.Mode); err != nil { |
|
log.Error("dao.DelAdvCache(%+v) error(%v)", adv, err) |
|
return |
|
} |
|
if af < 1 { |
|
err = ecode.DMAdvNoFound |
|
return |
|
} |
|
if adv.Refund == 0 { |
|
return |
|
} |
|
coin = model.AdvSPCoin |
|
reason = model.AdvSPCoinCancelReason |
|
if adv.Mode == model.AdvMode { |
|
coin = model.AdvCoin |
|
reason = model.AdvCoinCancelReason |
|
} |
|
if _, err = s.coinRPC.ModifyCoin(c, &coinmdl.ArgModifyCoin{Mid: adv.Mid, Count: coin, Reason: reason}); err != nil { |
|
log.Error("s.accRPC.AddCoin2(%v,%v,%v) error(%v)", adv.Mid, coin, reason, err) |
|
} |
|
return |
|
} |
|
|
|
// CancelAdvance 取消高级弹幕申请 |
|
func (s *Service) CancelAdvance(c context.Context, mid, id int64) (err error) { |
|
var ( |
|
adv *model.Advance |
|
coin float64 |
|
reason string |
|
af int64 |
|
) |
|
if adv, err = s.dao.Advance(c, mid, id); err != nil { |
|
log.Error("s.dao.Advance(%d,%d) error(%v)", mid, id, err) |
|
return |
|
} |
|
if adv == nil { |
|
err = ecode.DMAdvNoFound |
|
return |
|
} |
|
if af, err = s.dao.DelAdvance(c, id); err != nil { |
|
log.Error("s.dao.DelAdvance(%d) error(%v)", id, err) |
|
return |
|
} |
|
if err = s.dao.DelAdvCache(c, adv.Mid, adv.Cid, adv.Mode); err != nil { |
|
log.Error("s.dao.DelAdvCache(%+v) error(%v)", adv, err) |
|
return |
|
} |
|
if af < 1 { |
|
err = ecode.DMAdvNoFound |
|
return |
|
} |
|
if adv.Refund == 0 || adv.Type == model.AdvTypeDeny { |
|
return |
|
} |
|
coin = model.AdvSPCoin |
|
reason = model.AdvSPCoinCancelReason |
|
if adv.Mode == model.AdvMode { |
|
coin = model.AdvCoin |
|
reason = model.AdvCoinCancelReason |
|
} |
|
if _, err = s.coinRPC.ModifyCoin(c, &coinmdl.ArgModifyCoin{Mid: adv.Mid, Count: coin, Reason: reason}); err != nil { |
|
log.Error("s.accRPC.AddCoin2(%v,%v,%v) error(%v)", adv.Mid, coin, reason, err) |
|
} |
|
return |
|
} |
|
|
|
// UpdateAdvancePermit update advance permit. |
|
func (s *Service) UpdateAdvancePermit(c context.Context, mid int64, advPermit int8) (err error) { |
|
_, err = s.dao.AddUpperConfig(c, mid, advPermit) |
|
return |
|
} |
|
|
|
// AdvancePermit get advance permission. |
|
func (s *Service) AdvancePermit(c context.Context, mid int64) (advPermit int8, err error) { |
|
advPermit, err = s.dao.UpperConfig(c, mid) |
|
return |
|
}
|
|
|