369 lines
9.5 KiB
Go
369 lines
9.5 KiB
Go
|
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
|
|||
|
}
|